Skip to content

Commit 55d47b8

Browse files
javrudskyHarness
authored andcommitted
feat: [FME-4268]: Added Cost Categories Detail List to MCP Server (#17)
* Adding missing enum config to ccm cost categories detail list * Commented code removed * Fixing rebase issues * Adding Cloud Cost Management list cost categories detail documentation * Rebase with master * Fixed received parameters name * Added Claud Cost Managment - Categories detail list * Added List Cloud Cost Management tool * [CCM-tools] CCM Overview * Rebase with master branch * Fixing account id issue * Fixed account id field name * Added List Cloud Cost Management tool * [CCM-tools] CCM Overview * Rebase with master * [CCM-tools] CCM Overview * [CCM-tools] CCM Overview
1 parent 405bf2e commit 55d47b8

File tree

6 files changed

+305
-12
lines changed

6 files changed

+305
-12
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ Toolset Name: `registries`
5050
Toolset Name: `cloudcostmanagement`
5151

5252
- `get_ccm_overview`: Retrieve the cost overview for a specific account.
53-
- `list_ccm_cost_categories`: List all cost categories for a specified account.
53+
- `list_ccm_cost_categories`: List all cost categories names for a specified account.
54+
- `list_ccm_cost_categories_detail`: List all cost categories details for a specified account.
5455

5556
#### Logs Toolset
5657

client/cloudcostmanagement.go

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import (
44
"context"
55
"fmt"
66
"github.com/harness/harness-mcp/client/dto"
7+
"github.com/harness/harness-mcp/pkg/utils"
78
)
89

910
const (
1011
ccmBasePath = "ccm/api"
1112
ccmGetOverviewPath = ccmBasePath + "/overview?accountIdentifier=%s&startTime=%d&endTime=%d&groupBy=%s"
1213
ccmCostCategoryListPath = ccmBasePath + "/business-mapping/filter-panel?accountIdentifier=%s"
14+
ccmCostCategoryDetailListPath = ccmBasePath + "/business-mapping?accountIdentifier=%s" // This endpoint lists cost categories
1315
)
1416

1517
type CloudCostManagementService struct {
@@ -29,14 +31,14 @@ func (c *CloudCostManagementService) GetOverview(ctx context.Context, accID stri
2931
return ccmOverview, nil
3032
}
3133

32-
func (r *CloudCostManagementService) ListCostCategories(ctx context.Context, scope dto.Scope, opts *dto.CcmListCostCategoriesOptions) (*dto.CCMCostCategoryList, error) {
34+
func (r *CloudCostManagementService) ListCostCategories(ctx context.Context, scope dto.Scope, opts *dto.CCMListCostCategoriesOptions) (*dto.CCMCostCategoryList, error) {
3335
path := ccmCostCategoryListPath
3436
params := make(map[string]string)
3537
addScope(scope, params)
3638

3739
// Handle nil options by creating default options
3840
if opts == nil {
39-
opts = &dto.CcmListCostCategoriesOptions{}
41+
opts = &dto.CCMListCostCategoriesOptions{}
4042
}
4143

4244
if opts.CostCategory != "" {
@@ -56,3 +58,51 @@ func (r *CloudCostManagementService) ListCostCategories(ctx context.Context, sco
5658

5759
return costCategories, nil
5860
}
61+
62+
func (r *CloudCostManagementService) ListCostCategoriesDetail(ctx context.Context, scope dto.Scope, opts *dto.CCMListCostCategoriesDetailOptions) (*dto.CCMCostCategoryDetailList, error) {
63+
path := ccmCostCategoryDetailListPath
64+
params := make(map[string]string)
65+
66+
// Handle nil options by creating default options
67+
if opts == nil {
68+
opts = &dto.CCMListCostCategoriesDetailOptions{}
69+
}
70+
71+
setCCMPaginationDefault(&opts.CCMPaginationOptions)
72+
73+
if opts.SearchKey != "" {
74+
params["searchKey"] = opts.SearchKey
75+
}
76+
if opts.SortType != "" {
77+
params["sortType"] = opts.SortType
78+
}
79+
if opts.SortOrder != "" {
80+
params["sortOrder"] = opts.SortOrder
81+
}
82+
params["limit"] = fmt.Sprintf("%d", opts.Limit)
83+
params["offset"] = fmt.Sprintf("%d", opts.Offset)
84+
85+
costCategories := new(dto.CCMCostCategoryDetailList)
86+
87+
err := r.Client.Get(ctx, path, params, nil, &costCategories)
88+
if err != nil {
89+
return nil, fmt.Errorf("failed to list cloud cost management cost categories: %w", err)
90+
}
91+
92+
return costCategories, nil
93+
}
94+
95+
func setCCMPaginationDefault(opts *dto.CCMPaginationOptions) {
96+
if opts == nil {
97+
return
98+
}
99+
if opts.Offset <= 0 {
100+
opts.Offset = 1
101+
}
102+
safeMaxPageSize := utils.SafeIntToInt32(maxPageSize, 20)
103+
if opts.Limit <= 0 {
104+
opts.Limit = utils.SafeIntToInt32(defaultPageSize, 5)
105+
} else if opts.Limit > safeMaxPageSize {
106+
opts.Limit = safeMaxPageSize
107+
}
108+
}

client/dto/cloudcostmanagement.go

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ const (
99
PeriodTypeYear string = "YEAR"
1010
)
1111

12+
const (
13+
SortTypeName string = "NAME"
14+
SortTypeLastEdit string = "LAST_EDIT"
15+
)
16+
17+
const (
18+
SortOrderAsc string = "ASCENDING"
19+
SortOrderDesc string = "DESCENDING"
20+
)
21+
1222
// CEView represents a basic ccm response.
1323
// The `data` field contains the response data.
1424
type CCMBaseResponse struct {
@@ -56,8 +66,12 @@ type CCMReference struct {
5666
Type string `json:"type,omitempty"`
5767
}
5868

69+
// ***************************
70+
// Cost Category (name) List
71+
// ***************************
72+
5973
// CcmCostCategoriesOptions represents options for listing cost categories
60-
type CcmListCostCategoriesOptions struct {
74+
type CCMListCostCategoriesOptions struct {
6175
AccountIdentifier string `json:"accountIdentifier,omitempty"`
6276
CostCategory string `json:"costCategory,omitempty"`
6377
SearchTerm string `json:"search,omitempty"`
@@ -68,3 +82,113 @@ type CCMCostCategoryList struct {
6882
CCMBaseResponse
6983
Data []string `json:"data,omitempty"`
7084
}
85+
86+
// ***************************
87+
// Cost Category Details List
88+
// ***************************
89+
90+
type CCMPaginationOptions struct {
91+
Limit int32 `json:"limit,omitempty"`
92+
Offset int32 `json:"offset,omitempty"`
93+
}
94+
95+
type CCMListCostCategoriesDetailOptions struct {
96+
AccountIdentifier string `json:"accountIdentifier,omitempty"`
97+
SearchKey string `json:"searchKey,omitempty"`
98+
SortType string `json:"sortType,omitempty"` // Enum: "NAME", "LAST_EDIT"
99+
SortOrder string `json:"sortOrder,omitempty"` // Enum: "ASCENDING", "DESCENDING"
100+
CCMPaginationOptions
101+
}
102+
103+
type CCMCostCategoryDetailList struct {
104+
MetaData map[string]interface{} `json:"metaData"`
105+
Resource CCMCostCategoryResource `json:"resource"`
106+
ResponseMessages []CCMResponseMessage `json:"responseMessages"`
107+
}
108+
109+
type CCMCostCategoryResource struct {
110+
BusinessMappings []CCMBusinessMapping `json:"businessMappings"`
111+
TotalCount int `json:"totalCount"`
112+
}
113+
114+
type CCMBusinessMapping struct {
115+
UUID string `json:"uuid"`
116+
Name string `json:"name"`
117+
AccountID string `json:"accountId"`
118+
CostTargets []CCMCostTarget `json:"costTargets"`
119+
SharedCosts []CCMSharedCost `json:"sharedCosts"`
120+
UnallocatedCost CCMUnallocatedCost `json:"unallocatedCost"`
121+
DataSources []string `json:"dataSources"`
122+
CreatedAt int64 `json:"createdAt"`
123+
LastUpdatedAt int64 `json:"lastUpdatedAt"`
124+
CreatedBy CCMUser `json:"createdBy"`
125+
LastUpdatedBy CCMUser `json:"lastUpdatedBy"`
126+
}
127+
128+
type CCMCostTarget struct {
129+
Name string `json:"name"`
130+
Rules []CCMRule `json:"rules"`
131+
}
132+
133+
type CCMSharedCost struct {
134+
Name string `json:"name"`
135+
Rules []CCMRule `json:"rules"`
136+
Strategy string `json:"strategy"`
137+
Splits []CCMSplit `json:"splits"`
138+
}
139+
140+
type CCMUnallocatedCost struct {
141+
Strategy string `json:"strategy"`
142+
Label string `json:"label"`
143+
SharingStrategy string `json:"sharingStrategy"`
144+
Splits []CCMSplit `json:"splits"`
145+
}
146+
147+
type CCMSplit struct {
148+
CostTargetName *string `json:"costTargetName"`
149+
PercentageContribution *float64 `json:"percentageContribution"`
150+
}
151+
152+
type CCMRule struct {
153+
ViewConditions []interface{} `json:"viewConditions"`
154+
}
155+
156+
type CCMUser struct {
157+
UUID string `json:"uuid"`
158+
Name string `json:"name"`
159+
Email string `json:"email"`
160+
ExternalUserID string `json:"externalUserId"`
161+
}
162+
163+
type CCMResponseMessage struct {
164+
Code string `json:"code"`
165+
Level string `json:"level"`
166+
Message string `json:"message"`
167+
Exception *CCMException `json:"exception"`
168+
FailureTypes []string `json:"failureTypes"`
169+
AdditionalInfo map[string]string `json:"additionalInfo"`
170+
}
171+
172+
type CCMException struct {
173+
StackTrace []CCMStackTraceElement `json:"stackTrace"`
174+
Message string `json:"message"`
175+
Suppressed []CCMSuppressed `json:"suppressed"`
176+
LocalizedMessage string `json:"localizedMessage"`
177+
}
178+
179+
type CCMStackTraceElement struct {
180+
ClassLoaderName *string `json:"classLoaderName"`
181+
ModuleName *string `json:"moduleName"`
182+
ModuleVersion *string `json:"moduleVersion"`
183+
MethodName *string `json:"methodName"`
184+
FileName *string `json:"fileName"`
185+
LineNumber *int `json:"lineNumber"`
186+
NativeMethod *bool `json:"nativeMethod"`
187+
ClassName *string `json:"className"`
188+
}
189+
190+
type CCMSuppressed struct {
191+
StackTrace []CCMStackTraceElement `json:"stackTrace"`
192+
Message string `json:"message"`
193+
LocalizedMessage string `json:"localizedMessage"`
194+
}

0 commit comments

Comments
 (0)