cloud-barista / cb-spider

CB-Spider offers a unified view and interface for multi-cloud management.
https://github.com/cloud-barista/cb-spider/wiki
Apache License 2.0
33 stars 47 forks source link

initialize aws cost explorer getCostAndUsageWithResource anycall handler function #1309

Closed MZC-CSC closed 3 months ago

MZC-CSC commented 3 months ago

작업 내용


개요

getCostWithResource 함수는 지정된 매개변수에 따라 AWS Cost Explorer에서 AWS 리소스의 비용 및 사용량 데이터를 쿼리한다. spider 의 aws anycall handler 를 확장해서 기능을 구성했다.

함수 시그니처

func getCostWithResource(anyCallHandler *AwsAnyCallHandler, callInfo irs.AnyCallInfo) (irs.AnyCallInfo, error)

매개변수

anyCallHandler

callInfo

요청 구조 ‼️🎆✨

callInfo 매개변수는 requestBody 키 아래에 JSON 본문을 포함해야 한다. 이 JSON은 CostWithResourceReq구조에 맞아야하며 CostWithResourceReq는 다음과 같은 구조를 가진다.

CostWithResourceReq 구조

StartDate: string required

EndDate: string required

Granularity: string required

Metrics: []string required at least one element

Filter: FilterExpression required

Groups: []GroupBy optional

FilterExpression 구조

*`And: []FilterExpression`** optional

*`Or: []FilterExpression`** optional

*`Not: FilterExpression`** optional

*`CostCategories: KeyValues`** optional

*`Dimensions: KeyValues`** optional

*`Tags: KeyValues`** optional

KeyValues 구조

Key: string

Values: []string

GroupBy 구조

Type: string

Key: string

응답

함수는 AWS Cost Explorer의 응답으로 callInfo를 업데이트 한 후 리턴한다.

callInfo.OKeyValueList 키: "result" 값: AWS Cost Explorer 응답의 JSON 문자열.

오류

다음 경우에 오류를 반환한다.

요청 json 직렬화 형식 예시

{
  "startDate": "2024-08-14",
  "endDate": "2024-08-28",
  "granularity": "DAILY",
  "metrics": [
    "UnblendedCost", "BlendedCost"
  ],
  "filter": {
    "or": [
      {
        "and": [
          {
            "dimensions": {
              "key": "RESOURCE_ID",
              "values": [
                "i-0xxxxxxxxxec4",
                "i-0xxx1e3",
                "arn:aws:ec2:ap-northeast-2:xxxxxx:network-interface/eni-06cxxxxxx02e34",
                "vol-068xxxxx0",
                "vol-0xxxx"
              ]
            }
          },
          {
            "dimensions": {
              "key": "SERVICE",
              "values": [
                "Amazon Elastic Compute Cloud - Compute",
                "EC2 - Other",
                "Amazon Virtual Private Cloud",
                "EC2 - Other"
              ]
            }
          }
        ]
      },
      {
        "dimensions": {
          "key": "SERVICE",
          "values": [
            "AWS Cost Explorer",
            "Tax"
          ]
        }
      }
    ]
  },
  "groups": [
    {
      "key": "SERVICE",
      "type": "DIMENSION"
    },
    {
      "key": "RESOURCE_ID",
      "type": "DIMENSION"
    }
  ]
}

Curl 호출 예시

curl -X POST http://localhost:1024/spider/anycall \
  -H "Content-Type: application/json" \
  -d '{
    "ConnectionName": "your_connection_name",
    "ReqInfo": {
      "FID": "getCostWithResource",
      "IKeyValueList": [
        {
          "Key": "requestBody",
          "Value": "{\"startDate\":\"2024-08-14\",\"endDate\":\"2024-08-28\",\"granularity\":\"DAILY\",\"metrics\":[\"UnblendedCost\",\"BlendedCost\"],\"filter\":{\"or\":[{\"and\":[{\"dimensions\":{\"key\":\"RESOURCE_ID\",\"values\":[\"i-0xxxxxxxxxec4\",\"i-0xxx1e3\",\"arn:aws:ec2:ap-northeast-2:xxxxxx:network-interface/eni-06cxxxxxx02e34\",\"vol-068xxxxx0\",\"vol-0xxxx\"]}},{\"dimensions\":{\"key\":\"SERVICE\",\"values\":[\"Amazon Elastic Compute Cloud - Compute\",\"EC2 - Other\",\"Amazon Virtual Private Cloud\",\"EC2 - Other\"]}}]},{\"dimensions\":{\"key\":\"SERVICE\",\"values\":[\"AWS Cost Explorer\",\"Tax\"]}}]},\"groups\":[{\"key\":\"SERVICE\",\"type\":\"DIMENSION\"},{\"key\":\"RESOURCE_ID\",\"type\":\"DIMENSION\"}]}"
        }
      ]
    }
  }'

GO 코드 예시

costWithResourceReq := costWithResourceReq{
    StartDate:   param.StartDate.Format("2006-01-02"),
    EndDate:     param.EndDate.Format("2006-01-02"),
    Granularity: granularity,
    Metrics:     []string{metrics}, // BlendedCost, UnblendedCost, ...
    Filter: filterExpression{
        Or: []*filterExpression{
            {
                And: []*filterExpression{
                    {
                        Dimensions: &keyValues{
                            Key:    "RESOURCE_ID",
                            Values: resourceIdFilterValue,
                        },
                    },
                    {
                        Dimensions: &keyValues{
                            Key:    "SERVICE",
                            Values: serviceFilterValue,
                        },
                    },
                },
            },
            {
                Dimensions: &keyValues{
                    Key: "SERVICE",
                    Values: []string{
                        string(constant.AwsCostExplorer),
                        string(constant.AwsTax),
                    },
                },
            },
        },
    },
    // the order of group by will effect the result's key order
    Groups: []groupBy{
        {
            Key:  "SERVICE",
            Type: "DIMENSION",
        },
        {
            Key:  "RESOURCE_ID",
            Type: "DIMENSION",
        },
    },
}

m, err := json.Marshal(costWithResourceReq)
if err != nil {
    return nil, err
}

res, err := spider.GetCostWithResourceWithContext(
    ctx,
    spider.AnycallReq{
        ConnectionName: param.ConnectionName,
        ReqInfo: spider.ReqInfo{
            FID: "getCostWithResource",
            IKeyValueList: []spider.KeyValue{
                {
                    Key:   "requestBody",
                    Value: string(m),
                },
            },
        },
    },
)

응답 예시

{
  "DimensionValueAttributes": [],
  "GroupDefinitions": [
    {
      "Key": "SERVICE",
      "Type": "DIMENSION"
    },
    {
      "Key": "RESOURCE_ID",
      "Type": "DIMENSION"
    }
  ],
  "NextPageToken": null,
  "ResultsByTime": [
    {
      "Estimated": true,
      "Groups": [
        {
          "Keys": [
            "EC2 - Other",
            "i-xxxxxxxx"
          ],
          "Metrics": {
            "UnblendedCost": {
              "Amount": "0.000001897",
              "Unit": "USD"
            }
          }
        },
        {
          "Keys": [
            "EC2 - Other",
            "i-xxxxxx"
          ],
          "Metrics": {
            "UnblendedCost": {
              "Amount": "0.0050821397",
              "Unit": "USD"
            }
          }
        },
        {
          "Keys": [
            "EC2 - Other",
            "vol-0689axxxxxxx"
          ],
          "Metrics": {
            "UnblendedCost": {
              "Amount": "0.0367741944",
              "Unit": "USD"
            }
          }
        },
        {
          "Keys": [
            "EC2 - Other",
            "vol-0dxxxxxx572"
          ],
          "Metrics": {
            "UnblendedCost": {
              "Amount": "0.0367741944",
              "Unit": "USD"
            }
          }
        },
        {
          "Keys": [
            "Amazon Elastic Compute Cloud - Compute",
            "i-02xxxxxdec4"
          ],
          "Metrics": {
            "UnblendedCost": {
              "Amount": "0.6912",
              "Unit": "USD"
            }
          }
        },
        {
          "Keys": [
            "Amazon Elastic Compute Cloud - Compute",
            "i-xxxxxxxxxe3"
          ],
          "Metrics": {
            "UnblendedCost": {
              "Amount": "1.248",
              "Unit": "USD"
            }
          }
        },
        {
          "Keys": [
            "Amazon Virtual Private Cloud",
            "arn:aws:ec2:ap-northeast-2:05xxxxxxxx3:network-interface/eni-0xxxxe34"
          ],
          "Metrics": {
            "UnblendedCost": {
              "Amount": "0.12",
              "Unit": "USD"
            }
          }
        }
      ],
      "TimePeriod": {
        "End": "2024-08-15T00:00:00Z",
        "Start": "2024-08-14T00:00:00Z"
      },
      "Total": {}
    }
  ]
}
powerkimhub commented 3 months ago

@MZC-CSC @hippo-an