Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

정책 및 템플릿 버전업 통계 기능 추가 #361

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions internal/delivery/api/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ const (
GetPolicyEdit
AddPoliciesForStack
DeletePoliciesForStack
StackPolicyStatistics

// OrganizationPolicyTemplate
ListPolicyTemplate
Expand Down
8 changes: 8 additions & 0 deletions internal/delivery/api/generated_endpoints.go.go
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,10 @@ var ApiMap = map[Endpoint]EndpointInfo{
Name: "DeletePoliciesForStack",
Group: "Policy",
},
StackPolicyStatistics: {
Name: "StackPolicyStatistics",
Group: "Policy",
},
ListPolicyTemplate: {
Name: "ListPolicyTemplate",
Group: "OrganizationPolicyTemplate",
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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":
Expand Down
46 changes: 46 additions & 0 deletions internal/delivery/http/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions internal/policy-template/tkspolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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, "", " ")

Expand Down
45 changes: 45 additions & 0 deletions internal/policy-template/tkspolicytemplate.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
}
1 change: 1 addition & 0 deletions internal/route/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
79 changes: 79 additions & 0 deletions internal/usecase/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)

Expand Down
9 changes: 9 additions & 0 deletions pkg/domain/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
}
2 changes: 1 addition & 1 deletion pkg/httpErrors/errorCode.go
Original file line number Diff line number Diff line change
Expand Up @@ -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": "쿠버네티스 클러스터 변경사항 적용에 실패했습니다.",
}
Expand Down
Loading