Skip to content

Commit

Permalink
Merge pull request #361 from sangkenlee/policy-version-statistics
Browse files Browse the repository at this point in the history
정책 및 템플릿 버전업 통계 기능 추가
  • Loading branch information
seungkyua authored Apr 9, 2024
2 parents 3cc4a93 + 2cd6f86 commit 5ded835
Show file tree
Hide file tree
Showing 9 changed files with 194 additions and 1 deletion.
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/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)
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

0 comments on commit 5ded835

Please sign in to comment.