Skip to content

Commit

Permalink
Merge pull request #1127 from jolo-dev/feature/0457-support-amazon-cl…
Browse files Browse the repository at this point in the history
…oudfront-function

(feature/0457-support-amazon-cloudfront-function): Support Amazon Clo…
  • Loading branch information
mlabouardy committed Oct 30, 2023
2 parents 5cbaffa + cbad52d commit c136d61
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/configuration/cloud-providers/aws.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ sidebar_label: Amazon Web Services
- API Gateway
- Access control lists
- CloudFront distributions
- CloudFront functions
- CloudWatch Dashboards
- CloudWatch alarms
- CloudWatch metrics
Expand Down
1 change: 1 addition & 0 deletions policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"apigateway:GET",
"cloudwatch:GetMetricStatistics",
"cloudfront:ListDistributions",
"cloudfront:Functions",
"cloudfront:ListTagsForResource",
"cloudwatch:DescribeAlarms",
"cloudwatch:ListTagsForResource",
Expand Down
1 change: 1 addition & 0 deletions providers/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func listOfSupportedServices() []providers.FetchDataFunction {
ec2.Instances,
eks.KubernetesClusters,
cloudfront.Distributions,
cloudfront.Functions,
dynamodb.Tables,
ecs.Clusters,
ecs.TaskDefinitions,
Expand Down
115 changes: 115 additions & 0 deletions providers/aws/cloudfront/functions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package cloudfront

import (
"context"
"fmt"
"time"

log "github.com/sirupsen/logrus"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cloudfront"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch/types"
. "github.com/tailwarden/komiser/models"
. "github.com/tailwarden/komiser/providers"
"github.com/tailwarden/komiser/utils"
)

const (
freeTierInvocations = 2000000
costPerInvocation = 0.0000001
)

func Functions(ctx context.Context, client ProviderClient) ([]Resource, error) {
resources := make([]Resource, 0)
var config cloudfront.ListFunctionsInput
cloudfrontClient := cloudfront.NewFromConfig(*client.AWSClient)

tempRegion := client.AWSClient.Region
client.AWSClient.Region = "us-east-1"
cloudwatchClient := cloudwatch.NewFromConfig(*client.AWSClient)
client.AWSClient.Region = tempRegion

for {
output, err := cloudfrontClient.ListFunctions(ctx, &config)
if err != nil {
return resources, err
}

for _, function := range output.FunctionList.Items {
metricsInvocationsOutput, err := cloudwatchClient.GetMetricStatistics(ctx, &cloudwatch.GetMetricStatisticsInput{
StartTime: aws.Time(utils.BeginningOfMonth(time.Now())),
EndTime: aws.Time(time.Now()),
MetricName: aws.String("FunctionInvocations"),
Namespace: aws.String("AWS/CloudFront"),
Dimensions: []types.Dimension{
types.Dimension{
Name: aws.String("FunctionName"),
Value: function.Name,
},
},
Period: aws.Int32(3600),
Statistics: []types.Statistic{
types.StatisticSum,
},
})

if err != nil {
log.Warnf("Couldn't fetch invocations metric for %s", *function.Name)
return resources, err
}

invocations := 0.0
if metricsInvocationsOutput != nil && len(metricsInvocationsOutput.Datapoints) > 0 {
invocations = *metricsInvocationsOutput.Datapoints[0].Sum
}
if invocations > freeTierInvocations {
invocations -= freeTierInvocations
}

monthlyCost := invocations * costPerInvocation

outputTags, err := cloudfrontClient.ListTagsForResource(ctx, &cloudfront.ListTagsForResourceInput{
Resource: function.FunctionMetadata.FunctionARN,
})

tags := make([]Tag, 0)

if err == nil {
for _, tag := range outputTags.Tags.Items {
tags = append(tags, Tag{
Key: *tag.Key,
Value: *tag.Value,
})
}
}

resources = append(resources, Resource{
Provider: "AWS",
Account: client.Name,
Service: "CloudFront",
ResourceId: *function.FunctionMetadata.FunctionARN,
Region: client.AWSClient.Region,
Name: *function.Name,
Cost: monthlyCost,
Tags: tags,
FetchedAt: time.Now(),
Link: fmt.Sprintf("https://%s.console.aws.amazon.com/cloudfront/v3/home?region=%s#/functions/%s", client.AWSClient.Region, client.AWSClient.Region, *function.Name),
})
}

if aws.ToString(output.FunctionList.NextMarker) == "" {
break
}
config.Marker = output.FunctionList.NextMarker
}
log.WithFields(log.Fields{
"provider": "AWS",
"account": client.Name,
"region": client.AWSClient.Region,
"service": "CloudFront",
"resources": len(resources),
}).Info("Fetched resources")
return resources, nil
}

0 comments on commit c136d61

Please sign in to comment.