Skip to content
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
9 changes: 5 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (
github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible
github.com/aokoli/goutils v1.0.1
github.com/aws/aws-sdk-go v1.39.0
github.com/aws/aws-sdk-go-v2 v1.39.2
github.com/aws/aws-sdk-go-v2 v1.41.4
github.com/aws/aws-sdk-go-v2/config v1.31.12
github.com/aws/aws-sdk-go-v2/credentials v1.18.16
github.com/aws/aws-sdk-go-v2/service/organizations v1.45.3
Expand Down Expand Up @@ -55,18 +55,19 @@ require (
github.com/Azure/go-autorest/tracing v0.5.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.9 // indirect
github.com/aws/aws-sdk-go-v2/service/costexplorer v1.63.5 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.9 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.29.6 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 // indirect
github.com/aws/smithy-go v1.23.0 // indirect
github.com/aws/smithy-go v1.24.2 // indirect
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
github.com/beevik/etree v1.1.0 // indirect
github.com/bitly/go-simplejson v0.5.0 // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ github.com/aws/aws-sdk-go v1.39.0 h1:74BBwkEmiqBbi2CGflEh34l0YNtIibTjZsibGarkNjo
github.com/aws/aws-sdk-go v1.39.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go-v2 v1.39.2 h1:EJLg8IdbzgeD7xgvZ+I8M1e0fL0ptn/M47lianzth0I=
github.com/aws/aws-sdk-go-v2 v1.39.2/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY=
github.com/aws/aws-sdk-go-v2 v1.41.4 h1:10f50G7WyU02T56ox1wWXq+zTX9I1zxG46HYuG1hH/k=
github.com/aws/aws-sdk-go-v2 v1.41.4/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 h1:i8p8P4diljCr60PpJp6qZXNlgX4m2yQFpYk+9ZT+J4E=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1/go.mod h1:ddqbooRZYNoJ2dsTwOty16rM+/Aqmk/GOXrK8cg7V00=
github.com/aws/aws-sdk-go-v2/config v1.31.12 h1:pYM1Qgy0dKZLHX2cXslNacbcEFMkDMl+Bcj5ROuS6p8=
Expand All @@ -57,12 +59,18 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9 h1:Mv4Bc0mWmv6oDuSWTKnk+wg
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9/go.mod h1:IKlKfRppK2a1y0gy1yH6zD+yX5uplJ6UuPlgd48dJiQ=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 h1:se2vOWGD3dWQUtfn4wEjRQJb1HK1XsNIt825gskZ970=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9/go.mod h1:hijCGH2VfbZQxqCDN7bwz/4dzxV+hkyhjawAtdPWKZA=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 h1:CNXO7mvgThFGqOFgbNAP2nol2qAWBOGfqR/7tQlvLmc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20/go.mod h1:oydPDJKcfMhgfcgBUZaG+toBbwy8yPWubJXBVERtI4o=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 h1:6RBnKZLkJM4hQ+kN6E7yWFveOTg8NLPHAkqrs4ZPlTU=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9/go.mod h1:V9rQKRmK7AWuEsOMnHzKj8WyrIir1yUJbZxDuZLFvXI=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 h1:tN6W/hg+pkM+tf9XDkWUbDEjGLb+raoBMFsTodcoYKw=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20/go.mod h1:YJ898MhD067hSHA6xYCx5ts/jEd8BSOLtQDL3iZsvbc=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.9 h1:w9LnHqTq8MEdlnyhV4Bwfizd65lfNCNgdlNC6mM5paE=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.9/go.mod h1:LGEP6EK4nj+bwWNdrvX/FnDTFowdBNwcSPuZu/ouFys=
github.com/aws/aws-sdk-go-v2/service/costexplorer v1.63.5 h1:iNNJ6ZrQO37Xh12XjNncS3fq/11l1TzyZwBWcZMHWkY=
github.com/aws/aws-sdk-go-v2/service/costexplorer v1.63.5/go.mod h1:auLb1gCiI54TM7iUxSYu5MYSimWr0fL6t5/PgxkJOr0=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 h1:oegbebPEMA/1Jny7kvwejowCaHz1FWZAQ94WXFNCyTM=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1/go.mod h1:kemo5Myr9ac0U9JfSjMo9yHLtw+pECEHsFtJ9tqCEI8=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.0 h1:X0FveUndcZ3lKbSpIC6rMYGRiQTcUVRNH6X4yYtIrlU=
Expand All @@ -83,6 +91,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 h1:p3jIvqYwUZgu/XYeI48bJxOhvm47
github.com/aws/aws-sdk-go-v2/service/sts v1.38.6/go.mod h1:WtKK+ppze5yKPkZ0XwqIVWD4beCwv056ZbPQNoeHqM8=
github.com/aws/smithy-go v1.23.0 h1:8n6I3gXzWJB2DxBDnfxgBaSX6oe0d/t10qGz7OKqMCE=
github.com/aws/smithy-go v1.23.0/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng=
github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
github.com/basgys/goxml2json v1.1.1-0.20181031222924-996d9fc8d313 h1:fKPpQHBQgt4dQuG6x+yH4gdgtodFDgN9rvHzwJzTKeg=
Expand Down
141 changes: 141 additions & 0 deletions pkg/multicloud/aws/business.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package aws

import (
"context"
"sort"
"strconv"
"time"

aws2 "github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/costexplorer"
cetypes "github.com/aws/aws-sdk-go-v2/service/costexplorer/types"

api "yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/pkg/errors"
)

type SMonthBill struct {
Month string `json:"month"`
StartDate string `json:"start_date"`
EndDate string `json:"end_date"`
Currency string `json:"currency"`
Total float64 `json:"total"`
Metric string `json:"metric"`
Granularity string `json:"granularity"`
Services []SMonthBillServiceFee `json:"services"`
}

type SMonthBillServiceFee struct {
Service string `json:"service"`
Amount string `json:"amount"`
Unit string `json:"unit"`
}

func getMonthDateRange(month string) (string, string, error) {
monthStart, err := time.Parse("2006-01", month)
if err != nil {
return "", "", errors.Wrapf(err, "invalid month %q, expected YYYY-MM", month)
}
monthEnd := monthStart.AddDate(0, 1, 0)
return monthStart.Format("2006-01-02"), monthEnd.Format("2006-01-02"), nil
}

func (self *SAwsClient) getCostExplorerRegion() string {
if self.GetAccessEnv() == api.CLOUD_ACCESS_ENV_AWS_CHINA {
return "cn-northwest-1"
}
return "us-east-1"
}

func (self *SAwsClient) GetMonthBill(month string) (*SMonthBill, error) {
startDate, endDate, err := getMonthDateRange(month)
if err != nil {
return nil, err
}

cfg, err := self.getConfig(context.Background(), self.getCostExplorerRegion(), true)
if err != nil {
return nil, errors.Wrap(err, "getConfig")
}

ceCli := costexplorer.NewFromConfig(cfg)
resp, err := ceCli.GetCostAndUsage(context.Background(), &costexplorer.GetCostAndUsageInput{
TimePeriod: &cetypes.DateInterval{
Start: aws2.String(startDate),
End: aws2.String(endDate),
},
Granularity: cetypes.GranularityMonthly,
Metrics: []string{"UnblendedCost"},
GroupBy: []cetypes.GroupDefinition{
{
Type: cetypes.GroupDefinitionTypeDimension,
Key: aws2.String("SERVICE"),
},
},
})
if err != nil {
return nil, errors.Wrap(err, "GetCostAndUsage")
}

ret := &SMonthBill{
Month: month,
StartDate: startDate,
EndDate: endDate,
Metric: "UnblendedCost",
Granularity: string(cetypes.GranularityMonthly),
Services: make([]SMonthBillServiceFee, 0),
}

var total float64
for _, byTime := range resp.ResultsByTime {
for _, group := range byTime.Groups {
if len(group.Keys) == 0 {
continue
}
metric, ok := group.Metrics["UnblendedCost"]
if !ok {
continue
}
if len(ret.Currency) == 0 {
ret.Currency = aws2.ToString(metric.Unit)
}
amount := aws2.ToString(metric.Amount)
if len(amount) > 0 {
if val, parseErr := strconv.ParseFloat(amount, 64); parseErr == nil {
total += val
}
}
ret.Services = append(ret.Services, SMonthBillServiceFee{
Service: group.Keys[0],
Amount: amount,
Unit: aws2.ToString(metric.Unit),
})
}
}
ret.Total = total

sort.Slice(ret.Services, func(i, j int) bool {
iVal, iErr := strconv.ParseFloat(ret.Services[i].Amount, 64)
jVal, jErr := strconv.ParseFloat(ret.Services[j].Amount, 64)
if iErr != nil || jErr != nil {
return ret.Services[i].Amount > ret.Services[j].Amount
}
return iVal > jVal
})

return ret, nil
}
35 changes: 35 additions & 0 deletions pkg/multicloud/aws/shell/business.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package shell

import (
"yunion.io/x/pkg/util/shellutils"

"yunion.io/x/cloudmux/pkg/multicloud/aws"
)

func init() {
type AwsMonthBillOptions struct {
MONTH string `help:"Billing month, e.g. 2026-03"`
}
shellutils.R(&AwsMonthBillOptions{}, "month-bill", "Query AWS month bill overview", func(cli *aws.SRegion, args *AwsMonthBillOptions) error {
result, err := cli.GetClient().GetMonthBill(args.MONTH)
if err != nil {
return err
}
printObject(result)
return nil
})
}
4 changes: 4 additions & 0 deletions vendor/github.com/aws/aws-sdk-go-v2/aws/credentials.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions vendor/github.com/aws/aws-sdk-go-v2/aws/transport/http/client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading