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

initialize aws cost explorer getCostAndUsageWithResource anycall handler function #1309

Merged

Conversation

MZC-CSC
Copy link
Contributor

@MZC-CSC MZC-CSC commented Aug 29, 2024

작업 내용

  • aws cost explorer 사용을 위해 aws anycall handler 에 cost exeplorer client 추가
  • aws cost explorer 의 getCostAndUsageWithResources 호출을 위한 함수 구현

개요

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

함수 시그니처

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

매개변수

anyCallHandler

  • 타입: *AwsAnyCallHandler
  • 설명: AWS 호출 핸들러로, AWS Cost Explorer 클라이언트에 접근 가능

callInfo

  • 타입: irs.AnyCallInfo
  • 설명: 요청에 대한 정보를 포함하며, 응답으로 업데이트

요청 구조 ‼️🎆✨

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

CostWithResourceReq 구조

StartDate: string required

  • 설명: 비용 및 사용량 보고서의 시작 날짜 (형식: YYYY-MM-DD)
  • 조회 조건에 포함

EndDate: string required

  • 설명: 비용 및 사용량 보고서의 종료 날짜 (형식: YYYY-MM-DD)
  • 조회 조건에 미포함 - 2024-10-10 이라고 한 경우 2024-10-09 까지의 데이터만 제공

Granularity: string required

  • 설명: 데이터의 세분성 (HOURLY | DAILY | MONTHLY).
  • Hourly 는 오늘 기준 최대 14일 이내의 데이터만 조회 가능

Metrics: []string required at least one element

  • 설명: 검색할 메트릭 목록 (AmortizedCost | BlendedCost | NetAmortizedCost | NetUnblendedCost | NormalizedUsageAmount | UnblendedCost | UsageQuantity).

Filter: FilterExpression required

  • 설명: 데이터에 적용할 필터.

Groups: []GroupBy optional

  • 설명: 보고서의 그룹화 목록.

FilterExpression 구조

And: []*FilterExpression optional

  • 설명: 필터의 논리적 AND.
  • 재귀적으로 FilterExpression 구성

Or: []*FilterExpression optional

  • 설명: 필터의 논리적 OR.
  • 재귀적으로 FilterExpression 구성

Not: *FilterExpression optional

  • 설명: 필터의 논리적 NOT.
  • 재귀적으로 FilterExpression 구성

CostCategories: *KeyValues optional

  • 설명: 필터링할 비용 카테고리.

Dimensions: *KeyValues optional

  • 설명: 필터링할 차원.
  • Demension.SERVICE 타입으로 사용 가능한 리스트
    • AWS Glue
    • AWS Key Management Service
    • AWS Lambda
    • AWS Migration Hub Refactor Spaces
    • AWS Secrets Manager
    • AWS Step Functions
    • AWS Systems Manager
    • Amazon API Gateway
    • Amazon EC2 Container Registry (ECR)
    • Amazon Elastic Compute Cloud - Compute
    • Amazon Elastic Container Service for Kubernetes
    • Amazon Elastic Load Balancing
    • Amazon Lightsail
    • Amazon Location Service
    • Amazon Registrar
    • Amazon Relational Database Service
    • Amazon Route 53
    • Amazon Simple Notification Service
    • Amazon Simple Queue Service
    • Amazon Simple Storage Service
    • Amazon Virtual Private Cloud
    • AmazonCloudWatch
    • AWS Cost Explorer
    • EC2 - Other
    • Tax

Tags: *KeyValues optional

  • 설명: 필터링할 태그.

KeyValues 구조

Key: string

  • 설명: 필터의 키.

Values: []string

  • 설명: 키에 대한 값 목록.

GroupBy 구조

Type: string

  • 설명: 그룹화의 유형 (DIMENSION | TAG | COST_CATEGORY)

Key: string

  • 설명: 그룹화할 키.
  • DIMENSION 의 경우 사용 가능한 keys
    • AZ | INSTANCE_TYPE | LEGAL_ENTITY_NAME | INVOICING_ENTITY | LINKED_ACCOUNT | OPERATION | PLATFORM | PURCHASE_TYPE | SERVICE | TENANCY | RECORD_TYPE | USAGE_TYPE

응답

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

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

오류

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

  • callInfo에 requestBody가 누락된 경우.
  • JSON 언마샬링에 실패한 경우.
  • AWS Cost Explorer API 호출에 실패한 경우.

요청 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 powerkimhub merged commit 2e1f06f into cloud-barista:master Aug 29, 2024
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants