From 46c06feacbdbdc99f9dbaa07f6d1ecbf9af07e9d Mon Sep 17 00:00:00 2001 From: Brad Sickles Date: Thu, 30 Oct 2025 09:36:18 -0400 Subject: [PATCH 1/9] update deps --- go.mod | 99 +++++++++++++++++++++++++++++--------------------- go.sum | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+), 41 deletions(-) diff --git a/go.mod b/go.mod index cd99c1e..c7e5a55 100644 --- a/go.mod +++ b/go.mod @@ -3,54 +3,71 @@ module github.com/nullstone-io/infra-sdk go 1.24.0 require ( - github.com/aws/aws-sdk-go-v2 v1.38.0 - github.com/aws/aws-sdk-go-v2/credentials v1.18.4 - github.com/aws/aws-sdk-go-v2/service/apigateway v1.34.0 - github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.31.0 - github.com/aws/aws-sdk-go-v2/service/cloudfront v1.52.0 - github.com/aws/aws-sdk-go-v2/service/ec2 v1.243.0 - github.com/aws/aws-sdk-go-v2/service/ecs v1.63.0 - github.com/aws/aws-sdk-go-v2/service/efs v1.39.0 - github.com/aws/aws-sdk-go-v2/service/elasticache v1.49.0 - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.32.0 - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.49.0 - github.com/aws/aws-sdk-go-v2/service/kafka v1.42.0 - github.com/aws/aws-sdk-go-v2/service/mq v1.32.0 - github.com/aws/aws-sdk-go-v2/service/opensearch v1.51.0 - github.com/aws/aws-sdk-go-v2/service/rds v1.103.0 - github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.29.0 - github.com/aws/aws-sdk-go-v2/service/route53 v1.56.1 - github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0 - github.com/aws/aws-sdk-go-v2/service/sns v1.37.0 - github.com/aws/aws-sdk-go-v2/service/sqs v1.41.0 - github.com/aws/aws-sdk-go-v2/service/sts v1.37.0 - github.com/aws/smithy-go v1.22.5 - golang.org/x/net v0.0.0-20200301022130-244492dfa37a - gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20250814151520-6962f4e47dd6 + github.com/aws/aws-sdk-go-v2 v1.39.4 + github.com/aws/aws-sdk-go-v2/credentials v1.18.19 + github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.9 + github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.9 + github.com/aws/aws-sdk-go-v2/service/cloudfront v1.55.2 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.259.0 + github.com/aws/aws-sdk-go-v2/service/ecs v1.66.0 + github.com/aws/aws-sdk-go-v2/service/efs v1.41.0 + github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.8 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.9 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.51.3 + github.com/aws/aws-sdk-go-v2/service/kafka v1.44.1 + github.com/aws/aws-sdk-go-v2/service/mq v1.34.6 + github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.8 + github.com/aws/aws-sdk-go-v2/service/rds v1.108.5 + github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.9 + github.com/aws/aws-sdk-go-v2/service/route53 v1.59.1 + github.com/aws/aws-sdk-go-v2/service/s3 v1.89.0 + github.com/aws/aws-sdk-go-v2/service/sns v1.39.1 + github.com/aws/aws-sdk-go-v2/service/sqs v1.42.11 + github.com/aws/aws-sdk-go-v2/service/sts v1.38.9 + github.com/aws/smithy-go v1.23.1 + golang.org/x/net v0.46.0 + gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251028222640-d27c71d5cd3c ) require ( - github.com/agext/levenshtein v1.2.1 // indirect + github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v12 v12.0.0 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.2 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.11 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.11 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.11 // indirect + github.com/cristalhq/jwt/v3 v3.1.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/hashicorp/hcl/v2 v2.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/hashicorp/hcl/v2 v2.24.0 // indirect github.com/jinzhu/copier v0.4.0 // indirect github.com/kr/pretty v0.3.1 // indirect - github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/nullstone-io/module v0.2.10 // indirect - github.com/rogpeppe/go-internal v1.13.1 // indirect - github.com/spf13/afero v1.2.2 // indirect - github.com/tmccombs/hcl2json v0.3.2-0.20201111174327-c96737926b76 // indirect - github.com/zclconf/go-cty v1.6.1 // indirect - golang.org/x/mod v0.27.0 // indirect - golang.org/x/text v0.3.8 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/stretchr/testify v1.11.1 // indirect + github.com/tmccombs/hcl2json v0.6.8 // indirect + github.com/zclconf/go-cty v1.17.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect + go.opentelemetry.io/otel v1.38.0 // indirect + go.opentelemetry.io/otel/metric v1.38.0 // indirect + go.opentelemetry.io/otel/trace v1.38.0 // indirect + golang.org/x/mod v0.29.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/text v0.30.0 // indirect + golang.org/x/tools v0.38.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index d25cb09..e7ce8eb 100644 --- a/go.sum +++ b/go.sum @@ -1,74 +1,148 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= +github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= +github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg/v12 v12.0.0 h1:bNEQyAGak9tojivJNkoqWErVCQbjdL7GzRt3F8NvfJ0= github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/aws/aws-sdk-go-v2 v1.38.0 h1:UCRQ5mlqcFk9HJDIqENSLR3wiG1VTWlyUfLDEvY7RxU= github.com/aws/aws-sdk-go-v2 v1.38.0/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= +github.com/aws/aws-sdk-go-v2 v1.39.4 h1:qTsQKcdQPHnfGYBBs+Btl8QwxJeoWcOcPcixK90mRhg= +github.com/aws/aws-sdk-go-v2 v1.39.4/go.mod h1:yWSxrnioGUZ4WVv9TgMrNUeLV3PFESn/v+6T/Su8gnM= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 h1:6GMWV6CNpA/6fbFHnoAjrv4+LGfyTqZz2LtCHnspgDg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0/go.mod h1:/mXlTIVG9jbxkqDnr5UQNQxW1HRYxeGklkM9vAFeabg= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.2 h1:t9yYsydLYNBk9cJ73rgPhPWqOh/52fcWDQB5b1JsKSY= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.2/go.mod h1:IusfVNTmiSN3t4rhxWFaBAqn+mcNdwKtPcV16eYdgko= github.com/aws/aws-sdk-go-v2/credentials v1.18.4 h1:IPd0Algf1b+Qy9BcDp0sCUcIWdCQPSzDoMK3a8pcbUM= github.com/aws/aws-sdk-go-v2/credentials v1.18.4/go.mod h1:nwg78FjH2qvsRM1EVZlX9WuGUJOL5od+0qvm0adEzHk= +github.com/aws/aws-sdk-go-v2/credentials v1.18.19 h1:Jc1zzwkSY1QbkEcLujwqRTXOdvW8ppND3jRBb/VhBQc= +github.com/aws/aws-sdk-go-v2/credentials v1.18.19/go.mod h1:DIfQ9fAk5H0pGtnqfqkbSIzky82qYnGvh06ASQXXg6A= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3 h1:o9RnO+YZ4X+kt5Z7Nvcishlz0nksIt2PIzDglLMP0vA= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3/go.mod h1:+6aLJzOG1fvMOyzIySYjOFjcguGvVRL68R+uoRencN4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11 h1:7AANQZkF3ihM8fbdftpjhken0TP9sBzFbV/Ze/Y4HXA= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11/go.mod h1:NTF4QCGkm6fzVwncpkFQqoquQyOolcyXfbpC98urj+c= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3 h1:joyyUFhiTQQmVK6ImzNU9TQSNRNeD9kOklqTzyk5v6s= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3/go.mod h1:+vNIyZQP3b3B1tSLI0lxvrU9cfM7gpdRXMFfm67ZcPc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.11 h1:ShdtWUZT37LCAA4Mw2kJAJtzaszfSHFb5n25sdcv4YE= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.11/go.mod h1:7bUb2sSr2MZ3M/N+VyETLTQtInemHXb/Fl3s8CLzm0Y= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3 h1:ZV2XK2L3HBq9sCKQiQ/MdhZJppH/rH0vddEAamsHUIs= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3/go.mod h1:b9F9tk2HdHpbf3xbN7rUZcfmJI26N6NcJu/8OsBFI/0= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.11 h1:bKgSxk1TW//00PGQqYmrq83c+2myGidEclp+t9pPqVI= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.11/go.mod h1:vrPYCQ6rFHL8jzQA8ppu3gWX18zxjLIDGTeqDxkBmSI= github.com/aws/aws-sdk-go-v2/service/apigateway v1.34.0 h1:IZAET61abhm3dZEMPwU6VLiXKVL2Qwvg0q7Bukpz/kA= github.com/aws/aws-sdk-go-v2/service/apigateway v1.34.0/go.mod h1:WuGmD7SWYen7UZcDGptMvzl6bN5OZ1x+Io1eI5XN7kU= +github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.9 h1:9izRfGPf77V364SWt2NjmR/3VI7AgRAFZaDJHAtD9pI= +github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.9/go.mod h1:/a0evDW8qp3FPS7HxI+dG2u0K/9sdr3NBI1tiP5ViiU= github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.31.0 h1:bbHfZmF4H/PG5EEo0hXDyM/45XZDMbkscXolqardpB0= github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.31.0/go.mod h1:qlUNYJtHoTWiJQMJkgi93jwRNRt9uIOUSMZrwMODh7Y= +github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.9 h1:sMk/ugu7Ct4Zd/98Toofflm15Jpt+1ZVDxP1BhuhnEY= +github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.9/go.mod h1:aoFp4iEj5JG8/AssywlKPoFUBfsoLDM04/Q92ADm3Z0= github.com/aws/aws-sdk-go-v2/service/cloudfront v1.52.0 h1:rJcbtmScByQ6NBIXV97m6e8Rasd0zgvt1z84pdddU/4= github.com/aws/aws-sdk-go-v2/service/cloudfront v1.52.0/go.mod h1:qTc2+9g3YGM5d/u+c4tmHun6vmEKwBjJ7rEM6N3qGVI= +github.com/aws/aws-sdk-go-v2/service/cloudfront v1.55.2 h1:MnDEmZz8maF6Ge2GaK6T16jqPDhyesUODhMheFqUBqU= +github.com/aws/aws-sdk-go-v2/service/cloudfront v1.55.2/go.mod h1:Ql3i8VKmdfYCcDhG6OpVkGM60IN9fPDV/7aMHCH3lds= github.com/aws/aws-sdk-go-v2/service/ec2 v1.243.0 h1:s7mU5Zfa1ksg86BGjYKU03Bs63m5MY1ps4jOZFayBwM= github.com/aws/aws-sdk-go-v2/service/ec2 v1.243.0/go.mod h1:EeWmteKqZjaMj45MUmPET1SisFI+HkqWIRQoyjMivcc= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.259.0 h1:0BwB+z9JX7fleVvaZaUuzIHvGWiWn2BQLJIW2riEzDQ= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.259.0/go.mod h1:DT0XByGaNaOff3CtLVmj3jKcMeVDfOj5DkLD39UPJY0= github.com/aws/aws-sdk-go-v2/service/ecs v1.63.0 h1:ZeUDPcF93I5pE614AD8Le5a1e+383jjJ8lopM/WVfB8= github.com/aws/aws-sdk-go-v2/service/ecs v1.63.0/go.mod h1:k5xD9wMxhUgcFU0Q1F1iB3YJkmBmW7+o4rrsBg8yhdc= +github.com/aws/aws-sdk-go-v2/service/ecs v1.66.0 h1:+apffrlIoVKFtykMzQx9wn4Uk3Qjyrwq8kqubh0TOpA= +github.com/aws/aws-sdk-go-v2/service/ecs v1.66.0/go.mod h1:E9n0AAMdcWJ66TGaYOb9SeDDQKG8dYuftwJSt+v6cHg= github.com/aws/aws-sdk-go-v2/service/efs v1.39.0 h1:nxn7P1nAd7ThB1B0WASAKvjddJQcvLzaOo9iN4tp3ZU= github.com/aws/aws-sdk-go-v2/service/efs v1.39.0/go.mod h1:8Ij4/TIExqfWWjcyQy82/V/aec2kQruuyndljE+Vuo0= +github.com/aws/aws-sdk-go-v2/service/efs v1.41.0 h1:OR1o4u/nIvqv+jsZ8H3eHXi/dSYCz7LldGqkq0Ackmo= +github.com/aws/aws-sdk-go-v2/service/efs v1.41.0/go.mod h1:lFDyqDkf31PrYYD4ovdvRSDfMHmNc+vYrd6pgpFvQvk= github.com/aws/aws-sdk-go-v2/service/elasticache v1.49.0 h1:zJY3lR0AdRuigAub2GQkIMz/TP50Ia6R6VruPgWBIxk= github.com/aws/aws-sdk-go-v2/service/elasticache v1.49.0/go.mod h1:CeEl4WwCPhtncasl9kdhSp1rigeO3HdVJ3hiPu6ZdZI= +github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.8 h1:qXfdy9KaBDV4XhAvkMXRuDNPR5BOWNh/d4mrsERRWg8= +github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.8/go.mod h1:uiPTYuaQyaWsPvH45Pae/8gA3o8i6QLFVj8B/FaD6BQ= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.32.0 h1:FO6LzHczDXByBf8+WJ5cswxaGy1EOjDVXA3NQa97Bh8= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.32.0/go.mod h1:q2K5uszrJv1SBxKYp5M9KUf7XR/Xnu38vSCiQ/wwhfI= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.9 h1:FqNGRAEtxCVek0rkz8rbxjqQu+yCdPsgQpBHbqoT6oE= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.9/go.mod h1:Oc5IwJcGA5MlCZcn2v9u5ke2D2TuST7tCDhKYup6DB8= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.49.0 h1:2VJj7fSoDawAjQ91u/DtrrUDOGsuMaWxcbe9Ok/O27w= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.49.0/go.mod h1:vJgvNz01VmSuXKzoUwQxQCzYklI/f09wXCWoj6TBGJE= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.51.3 h1:xKXVGDuAA1teDKhga/ds3N+pQkbcq9ON3RnnEhXnOdw= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.51.3/go.mod h1:gKD1BXAg9fRSxeFlSYkYEO3uxfhNXUyrtXUUDoc7WSI= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2 h1:xtuxji5CS0JknaXoACOunXOYOQzgfTvGAc9s2QdCJA4= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2/go.mod h1:zxwi0DIR0rcRcgdbl7E2MSOvxDyyXGBlScvBkARFaLQ= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3 h1:3ZKmesYBaFX33czDl6mbrcHb6jeheg6LqjJhQdefhsY= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3/go.mod h1:7ryVb78GLCnjq7cw45N6oUb9REl7/vNUwjvIqC5UgdY= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.2 h1:DGFpGybmutVsCuF6vSuLZ25Vh55E3VmsnJmFfjeBx4M= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.2/go.mod h1:hm/wU1HDvXCFEDzOLorQnZZ/CVvPXvWEmHMSmqgQRuA= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3 h1:ieRzyHXypu5ByllM7Sp4hC5f/1Fy5wqxqY0yB85hC7s= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3/go.mod h1:O5ROz8jHiOAKAwx179v+7sHMhfobFVi6nZt8DEyiYoM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11 h1:GpMf3z2KJa4RnJ0ew3Hac+hRFYLZ9DDjfgXjuW+pB54= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11/go.mod h1:6MZP3ZI4QQsgUCFTwMZA2V0sEriNQ8k2hmoHF3qjimQ= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3 h1:SE/e52dq9a05RuxzLcjT+S5ZpQobj3ie3UTaSf2NnZc= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3/go.mod h1:zkpvBTsR020VVr8TOrwK2TrUW9pOir28sH5ECHpnAfo= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.11 h1:weapBOuuFIBEQ9OX/NVW3tFQCvSutyjZYk/ga5jDLPo= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.11/go.mod h1:3C1gN4FmIVLwYSh8etngUS+f1viY6nLCDVtZmrFbDy0= github.com/aws/aws-sdk-go-v2/service/kafka v1.42.0 h1:/EB9p30Te0eClIIptu3g3meO38O87YVVdE/UVbyTvWA= github.com/aws/aws-sdk-go-v2/service/kafka v1.42.0/go.mod h1:uvEnl4e5ie3zB+2qlQCqcv0CgOyI8ajOegLEKERjqfs= +github.com/aws/aws-sdk-go-v2/service/kafka v1.44.1 h1:7pL53Xx0y+U6QTnDig6lEstKPie4yFkzDwm/xlv8jVw= +github.com/aws/aws-sdk-go-v2/service/kafka v1.44.1/go.mod h1:wcD5HEMcPgVNbIKhL/Q07FFtsCt+30WtvUqbA5OVdpU= github.com/aws/aws-sdk-go-v2/service/mq v1.32.0 h1:h04Kq2u2B6bDeAmNoxlf9bqtKH3GUlkW3p/+e/mE7+o= github.com/aws/aws-sdk-go-v2/service/mq v1.32.0/go.mod h1:tVSPpsQhalaf+DchZKFeDoohUeNE8dVSFGNRjZrDSQE= +github.com/aws/aws-sdk-go-v2/service/mq v1.34.6 h1:/LZXn/hzI14D04Zl7j3wDQpQmQx9UGqwnKLwKlRKZaY= +github.com/aws/aws-sdk-go-v2/service/mq v1.34.6/go.mod h1:CK40LT9yOzs/YJ8w46mp2pWBMkduiMdkDr/dO2FrUyU= github.com/aws/aws-sdk-go-v2/service/opensearch v1.51.0 h1:dxYQ9hDRI/yXFzO3sYT+x3Ss2d8JDf2eX5hyUPHG6fA= github.com/aws/aws-sdk-go-v2/service/opensearch v1.51.0/go.mod h1:NQvq4ckAgpR9/QqqI5+eWnP6rNlpOVta9udBG9GVHcw= +github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.8 h1:lFeAFG+OOMbUFcTgsROi1uIjOOCLA6pWAgL4SfTiGBY= +github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.8/go.mod h1:Vl3ROh8aYzg2O8dqmT+vQ0K9bIMoZMkWYl0BzYctlSg= github.com/aws/aws-sdk-go-v2/service/rds v1.103.0 h1:OWsmICx9jHtBVrgYwYb+2q0iVSPLIfDZOiKhoQA+gjc= github.com/aws/aws-sdk-go-v2/service/rds v1.103.0/go.mod h1:tUKTkGAlJo0Gs4t0Z46vaSGD6H1Z6RvtuF03mZY+tPk= +github.com/aws/aws-sdk-go-v2/service/rds v1.108.5 h1:Rxc/LXqxopzlCJATNOdaJ4pDCcLCOEYz+qJv2RagYho= +github.com/aws/aws-sdk-go-v2/service/rds v1.108.5/go.mod h1:9wC1x+2lS3i2HgPfkabhzms6Hga49X+lOUTppHnhJgM= github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.29.0 h1:jevrLpVG9sOEPsuipO3eGcdDzJyo36Dmme9iSu/8GVE= github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.29.0/go.mod h1:t/zZb99l0WrcNYbDIF3tgj0rJNklhiVa6B1x/Rz4rHc= +github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.9 h1:x4J04vxdladHgy+ZPsYbgZ3B6KDeIzYvGbnFOMu3DjE= +github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.9/go.mod h1:XDxyme5t2QvddctkZPZPHhjf0sMIO+unwz1nXg8pYOI= github.com/aws/aws-sdk-go-v2/service/route53 v1.56.1 h1:EqIPe7aD4cdk0xJINBhnxmifR/+T5TuXIHn2ivu8zKQ= github.com/aws/aws-sdk-go-v2/service/route53 v1.56.1/go.mod h1:aSIshIhq15I4lMlrkvvIoH7E4eLTAEW+isWbga9guNg= +github.com/aws/aws-sdk-go-v2/service/route53 v1.59.1 h1:KuoA/cmy/yK8n9v/d6WH36cZwGxFOrn0TmZ4lNN3MKQ= +github.com/aws/aws-sdk-go-v2/service/route53 v1.59.1/go.mod h1:BymbICXBfXQHO6i+yTBhocA9a6DM0uMDQqYelqa9wzs= github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0 h1:egoDf+Geuuntmw79Mz6mk9gGmELCPzg5PFEABOHB+6Y= github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0/go.mod h1:t9MDi29H+HDbkolTSQtbI0HP9DemAWQzUjmWC7LGMnE= +github.com/aws/aws-sdk-go-v2/service/s3 v1.89.0 h1:JbCUlVDEjmhpvpIgXP9QN+/jW61WWWj99cGmxMC49hM= +github.com/aws/aws-sdk-go-v2/service/s3 v1.89.0/go.mod h1:UHKgcRSx8PVtvsc1Poxb/Co3PD3wL7P+f49P0+cWtuY= github.com/aws/aws-sdk-go-v2/service/sns v1.37.0 h1:+GWmgZ6TeJ12tLw4l981+5nc9FDdzXtdZlnmp6KVHig= github.com/aws/aws-sdk-go-v2/service/sns v1.37.0/go.mod h1:O4eFpSa/AodvDLJqarL+0vnRgDP9d/FEKHZmzLnA/1c= +github.com/aws/aws-sdk-go-v2/service/sns v1.39.1 h1:GKg/7I4IGRrAm0j5Hwxrk8B9LXhzfxyDoDazW5XB7Ew= +github.com/aws/aws-sdk-go-v2/service/sns v1.39.1/go.mod h1:jQSGNtQAakrW+5vvUF5398mxsHryy0rsYWUXIQoHDAw= github.com/aws/aws-sdk-go-v2/service/sqs v1.41.0 h1:xobvQ4NxlXFUNgVwE6cnMI/ww7K7jtQMWKor2Gi61Xg= github.com/aws/aws-sdk-go-v2/service/sqs v1.41.0/go.mod h1:RExz4LhRKY5iogQ1dz7KVa3JyBY0PBotXovrDj850Sc= +github.com/aws/aws-sdk-go-v2/service/sqs v1.42.11 h1:tt34G790giMoWqpqJOfvc5BD25hHRSjgvx1x1jtwi9w= +github.com/aws/aws-sdk-go-v2/service/sqs v1.42.11/go.mod h1:tj8YTswoacIeRGjkYuHOkUd4ioQ4Of0m+gy09kuns9o= github.com/aws/aws-sdk-go-v2/service/sts v1.37.0 h1:MG9VFW43M4A8BYeAfaJJZWrroinxeTi2r3+SnmLQfSA= github.com/aws/aws-sdk-go-v2/service/sts v1.37.0/go.mod h1:JdeBDPgpJfuS6rU/hNglmOigKhyEZtBmbraLE4GK1J8= +github.com/aws/aws-sdk-go-v2/service/sts v1.38.9 h1:Ekml5vGg6sHSZLZJQJagefnVe6PmqC2oiRkBq4F7fU0= +github.com/aws/aws-sdk-go-v2/service/sts v1.38.9/go.mod h1:/e15V+o1zFHWdH3u7lpI3rVBcxszktIKuHKCY2/py+k= github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw= github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= +github.com/aws/smithy-go v1.23.1 h1:sLvcH6dfAFwGkHLZ7dGiYF7aK6mg4CgKA/iDKjLDt9M= +github.com/aws/smithy-go v1.23.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cristalhq/jwt/v3 v3.1.0 h1:iLeL9VzB0SCtjCy9Kg53rMwTcrNm+GHyVcz2eUujz6s= +github.com/cristalhq/jwt/v3 v3.1.0/go.mod h1:XOnIXst8ozq/esy5N1XOlSyQqBd+84fxJ99FK+1jgL8= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -79,8 +153,12 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/hcl/v2 v2.6.0 h1:3krZOfGY6SziUXa6H9PJU6TyohHn7I+ARYnhbeNBz+o= github.com/hashicorp/hcl/v2 v2.6.0/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY= +github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQxvE= +github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -94,6 +172,8 @@ github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3v github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/nullstone-io/module v0.2.10 h1:wCKrlyxyH9XQW5HliW/V6qNsDgUQxUCcWL60Ojlz+2U= github.com/nullstone-io/module v0.2.10/go.mod h1:btQiO0giVWDvvaQ7CLnPmuPPakJc55lAr8OlE1LK6hg= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -102,17 +182,24 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tmccombs/hcl2json v0.3.2-0.20201111174327-c96737926b76 h1:fUns9d7I0QAm9xW/xVgtys0B0UplMuopZHgKQEE+nrc= github.com/tmccombs/hcl2json v0.3.2-0.20201111174327-c96737926b76/go.mod h1:ljY0/prd2IFUF3cagQjV3cpPEEQKzqyGqnKI7m5DBVY= +github.com/tmccombs/hcl2json v0.6.8 h1:9bd7c3jZTj9FsN+lDIzrvLmXqxvCgydb84Uc4DBxOHA= +github.com/tmccombs/hcl2json v0.6.8/go.mod h1:qjEaQ4hBNPeDWOENB9yg6+BzqvtMA1MMN1+goFFh8Vc= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= @@ -120,16 +207,34 @@ github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgq github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= github.com/zclconf/go-cty v1.6.1 h1:wHtZ+LSSQVwUSb+XIJ5E9hgAQxyWATZsAWT+ESJ9dQ0= github.com/zclconf/go-cty v1.6.1/go.mod h1:VDR4+I79ubFBGm1uJac1226K5yANQFHeauxPBoP54+o= +github.com/zclconf/go-cty v1.17.0 h1:seZvECve6XX4tmnvRzWtJNHdscMtYEx5R7bnnVyd/d0= +github.com/zclconf/go-cty v1.17.0/go.mod h1:wqFzcImaLTI6A5HfsRwB0nj5n0MRZFwmey8YoFPPs3U= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -137,13 +242,19 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20250814151520-6962f4e47dd6 h1:+OMGXr7B93pg98thoBBf01sFkkFYJ7Vl0iVUXqqVZOI= gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20250814151520-6962f4e47dd6/go.mod h1:JE4cnrQcRkYZtl5HWkwJ2S4Oep8d1iv6lYQRQ5BC7cU= +gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251028222640-d27c71d5cd3c h1:0tx+r3tgGorPT6EWXawRiT3PFi5GBPMW1OIuc6kW+9U= +gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251028222640-d27c71d5cd3c/go.mod h1:Bj01hknD135uWb7j+9EIcE775ZXYv9pWSXdryTHMrhM= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 8abe94c4e0164dc19692e44adf59196e5124c75b Mon Sep 17 00:00:00 2001 From: Brad Sickles Date: Thu, 30 Oct 2025 10:55:07 -0400 Subject: [PATCH 2/9] Initial draft of aws coster --- .gitignore | 2 +- .../aws/aws-account/cost_result_aggregator.go | 77 +++++++++++ builtin/aws/aws-account/coster.go | 124 ++++++++++++++++++ builtin/aws/aws-account/pointers.go | 13 ++ builtin/aws/aws-account/scan_route53.go | 6 +- coster.go | 109 +++++++++++++++ examples/aws/bootstrap/coster.go | 30 +++++ examples/aws/daily_by_env/main.go | 49 +++++++ examples/aws/daily_for_env_by_block/main.go | 54 ++++++++ go.mod | 20 +-- go.sum | 116 +--------------- standard_tags.go | 33 +++++ 12 files changed, 501 insertions(+), 132 deletions(-) create mode 100644 builtin/aws/aws-account/cost_result_aggregator.go create mode 100644 builtin/aws/aws-account/coster.go create mode 100644 builtin/aws/aws-account/pointers.go create mode 100644 coster.go create mode 100644 examples/aws/bootstrap/coster.go create mode 100644 examples/aws/daily_by_env/main.go create mode 100644 examples/aws/daily_for_env_by_block/main.go create mode 100644 standard_tags.go diff --git a/.gitignore b/.gitignore index 77f9775..e8b2c34 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,7 @@ go.work go.work.sum # env file -.env +*.env # Editor/IDE .idea/ diff --git a/builtin/aws/aws-account/cost_result_aggregator.go b/builtin/aws/aws-account/cost_result_aggregator.go new file mode 100644 index 0000000..4bf0097 --- /dev/null +++ b/builtin/aws/aws-account/cost_result_aggregator.go @@ -0,0 +1,77 @@ +package aws_account + +import ( + "fmt" + "sort" + "strings" + "time" + + cetypes "github.com/aws/aws-sdk-go-v2/service/costexplorer/types" + infra_sdk "github.com/nullstone-io/infra-sdk" +) + +func NewCostResultAggregator() *CostResultAggregator { + return &CostResultAggregator{ + CostResult: infra_sdk.NewCostResult(), + } +} + +type CostResultAggregator struct { + CostResult *infra_sdk.CostResult +} + +func (a *CostResultAggregator) AddResults(resultsByTime []cetypes.ResultByTime) error { + for _, resultByTime := range resultsByTime { + start, end, err := a.parseWindow(resultByTime) + if err != nil { + return fmt.Errorf("error parsing result: %w", err) + } + + for _, grp := range resultByTime.Groups { + grpKeys := a.parseResultGroupKeys(grp.Keys) + for metricName, metricValue := range grp.Metrics { + a.CostResult.AddDatapoint(metricName, grpKeys, infra_sdk.CostSeriesDatapoint{ + Start: start, + End: end, + Unit: unptr(metricValue.Unit), + Value: unptr(metricValue.Amount), + }) + } + } + } + return nil +} + +func (a *CostResultAggregator) parseWindow(resultByTime cetypes.ResultByTime) (time.Time, time.Time, error) { + if resultByTime.TimePeriod == nil { + return time.Time{}, time.Time{}, fmt.Errorf("missing time period in results") + } + rawStart, rawEnd := unptr(resultByTime.TimePeriod.Start), unptr(resultByTime.TimePeriod.End) + start, err := time.Parse("2006-01-02", rawStart) + if err != nil { + return time.Time{}, time.Time{}, fmt.Errorf("invalid start time in results %q: %w", rawStart, err) + } + end, err := time.Parse("2006-01-02", rawEnd) + if err != nil { + return time.Time{}, time.Time{}, fmt.Errorf("invalid end time in results %q: %w", rawEnd, err) + } + return start, end, nil +} + +func (a *CostResultAggregator) parseResultGroupKeys(keys []string) infra_sdk.CostSeriesGroupKeys { + sort.Strings(keys) + + result := make(infra_sdk.CostSeriesGroupKeys, 0) + for _, key := range keys { + tokens := strings.SplitN(key, "$", 2) + if len(tokens) == 2 { + result = append(result, infra_sdk.CostSeriesGroupKey{ + TagKey: infra_sdk.MapLegacyTagToStandard(tokens[0]), + TagValue: tokens[1], + }) + } else { + result = append(result, infra_sdk.CostSeriesGroupKey{Name: key}) + } + } + return result +} diff --git a/builtin/aws/aws-account/coster.go b/builtin/aws/aws-account/coster.go new file mode 100644 index 0000000..e9e9f9e --- /dev/null +++ b/builtin/aws/aws-account/coster.go @@ -0,0 +1,124 @@ +package aws_account + +import ( + "context" + "encoding/json" + "fmt" + "log" + + ce "github.com/aws/aws-sdk-go-v2/service/costexplorer" + cetypes "github.com/aws/aws-sdk-go-v2/service/costexplorer/types" + infra_sdk "github.com/nullstone-io/infra-sdk" + "github.com/nullstone-io/infra-sdk/access/aws" + "gopkg.in/nullstone-io/go-api-client.v0/types" +) + +var ( + granularityMappings = map[infra_sdk.CostGranularity]cetypes.Granularity{ + infra_sdk.CostGranularityHourly: cetypes.GranularityHourly, + infra_sdk.CostGranularityDaily: cetypes.GranularityDaily, + infra_sdk.CostGranularityMonthly: cetypes.GranularityMonthly, + } +) + +type Coster struct { + Assumer aws.Assumer + Provider types.Provider +} + +func (c Coster) GetCosts(ctx context.Context, query infra_sdk.CostQuery) (*infra_sdk.CostResult, error) { + // Cost Explorer is global, use us-east-1 as the region to satisfy the aws sdk + providerConfig := types.ProviderConfig{Aws: &types.AwsProviderConfig{Region: "us-east-1"}} + awsConfig, err := aws.ResolveConfig(c.Assumer.AwsConfig(), c.Provider, providerConfig) + if err != nil { + return nil, fmt.Errorf("error resolving aws config: %w", err) + } + client := ce.NewFromConfig(awsConfig) + + period := &cetypes.DateInterval{ + Start: ptr(query.Start.Format("2006-01-02")), + End: ptr(query.End.Format("2006-01-02")), // end is EXCLUSIVE + } + + granularity := granularityMappings[query.Granularity] + if granularity == "" { + granularity = cetypes.GranularityDaily + } + + input := &ce.GetCostAndUsageInput{ + TimePeriod: period, + Granularity: granularity, + Metrics: []string{"UnblendedCost"}, + Filter: costQueryToFilter(query), + GroupBy: costQueryToGroupBy(query), + } + rawInput, _ := json.Marshal(input) + log.Println("input", string(rawInput)) + + aggregator := NewCostResultAggregator() + var nextToken *string + for { + input.NextPageToken = nextToken + out, err := client.GetCostAndUsage(ctx, input) + if err != nil { + return nil, fmt.Errorf("error querying aws cost explorer: %w", err) + } + if err := aggregator.AddResults(out.ResultsByTime); err != nil { + return nil, fmt.Errorf("error aggregating results: %w", err) + } + if out.NextPageToken == nil || *out.NextPageToken == "" { + break + } + nextToken = out.NextPageToken + } + + return aggregator.CostResult, nil +} + +func costQueryToFilter(query infra_sdk.CostQuery) *cetypes.Expression { + if len(query.FilterTags) < 1 { + return nil + } + if len(query.FilterTags) == 1 { + return &cetypes.Expression{ + Tags: &cetypes.TagValues{ + Key: ptr(infra_sdk.MapStandardTagToLegacy(query.FilterTags[0].Key)), + MatchOptions: []cetypes.MatchOption{cetypes.MatchOptionEquals}, + Values: query.FilterTags[0].Values, + }, + } + } + + root := &cetypes.Expression{} + for _, filterTag := range query.FilterTags { + root.And = append(root.And, cetypes.Expression{ + Tags: &cetypes.TagValues{ + Key: ptr(infra_sdk.MapStandardTagToLegacy(filterTag.Key)), + MatchOptions: []cetypes.MatchOption{cetypes.MatchOptionEquals}, + Values: filterTag.Values, + }, + }) + } + return root +} + +func costQueryToGroupBy(query infra_sdk.CostQuery) []cetypes.GroupDefinition { + if len(query.GroupTags) < 1 { + return nil + } + + // Don't allow duplicate group tags + unique := map[string]bool{} + for _, groupTag := range query.GroupTags { + unique[infra_sdk.MapStandardTagToLegacy(groupTag.Key)] = true + } + + var groupBy []cetypes.GroupDefinition + for key := range unique { + groupBy = append(groupBy, cetypes.GroupDefinition{ + Key: ptr(key), + Type: cetypes.GroupDefinitionTypeTag, + }) + } + return groupBy +} diff --git a/builtin/aws/aws-account/pointers.go b/builtin/aws/aws-account/pointers.go new file mode 100644 index 0000000..43ede4f --- /dev/null +++ b/builtin/aws/aws-account/pointers.go @@ -0,0 +1,13 @@ +package aws_account + +func ptr[T any](t T) *T { + return &t +} + +func unptr[T any](t *T) T { + var result T + if t != nil { + result = *t + } + return result +} diff --git a/builtin/aws/aws-account/scan_route53.go b/builtin/aws/aws-account/scan_route53.go index aeb0b29..a3601cf 100644 --- a/builtin/aws/aws-account/scan_route53.go +++ b/builtin/aws/aws-account/scan_route53.go @@ -3,14 +3,14 @@ package aws_account import ( "context" "fmt" + "strings" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/route53" r53types "github.com/aws/aws-sdk-go-v2/service/route53/types" - "github.com/aws/smithy-go/ptr" infra_sdk "github.com/nullstone-io/infra-sdk" "golang.org/x/net/publicsuffix" "gopkg.in/nullstone-io/go-api-client.v0/types" - "strings" ) // ScanRoute53 scans Route53 hosted zones and returns them as scan resources @@ -85,7 +85,7 @@ func getHostedZoneTags(ctx context.Context, client *route53.Client, zoneId strin } for _, tag := range output.ResourceTagSet.Tags { - tags[ptr.ToString(tag.Key)] = ptr.ToString(tag.Value) + tags[unptr(tag.Key)] = unptr(tag.Value) } return tags, nil diff --git a/coster.go b/coster.go new file mode 100644 index 0000000..b257a4e --- /dev/null +++ b/coster.go @@ -0,0 +1,109 @@ +package infra_sdk + +import ( + "context" + "fmt" + "strings" + "time" +) + +type CostGranularity string + +const ( + CostGranularityHourly CostGranularity = "hourly" + CostGranularityDaily CostGranularity = "daily" + CostGranularityMonthly CostGranularity = "monthly" +) + +type Coster interface { + GetCosts(ctx context.Context, query CostQuery) (CostResult, error) +} + +type CostQuery struct { + Start time.Time `json:"start"` + End time.Time `json:"end"` + Granularity CostGranularity `json:"granularity"` + FilterTags []CostFilterTag `json:"filterTags"` + GroupTags []CostGroupTag `json:"groupTags"` +} + +type CostFilterTag struct { + Key string `json:"key"` + Values []string `json:"values"` +} + +type CostGroupTag struct { + Key string `json:"key"` +} + +type CostResult struct { + Series map[string]CostSeries `json:"series"` +} + +func (r *CostResult) AddDatapoint(metricName string, groupKeys CostSeriesGroupKeys, datapoint CostSeriesDatapoint) { + seriesKey := fmt.Sprintf("%s:%s", groupKeys.UniqueIdentifier(), metricName) + cur, ok := r.Series[seriesKey] + if !ok { + cur = CostSeries{ + MetricName: metricName, + GroupKeys: groupKeys, + Points: []CostSeriesDatapoint{}, + } + } + cur.Points = append(cur.Points, datapoint) + r.Series[seriesKey] = cur +} + +func NewCostResult() *CostResult { + return &CostResult{ + Series: map[string]CostSeries{}, + } +} + +type CostSeries struct { + MetricName string `json:"metricName"` + GroupKeys CostSeriesGroupKeys `json:"groupKeys"` + Points []CostSeriesDatapoint `json:"points"` +} + +type CostSeriesGroupKeys []CostSeriesGroupKey + +func (s CostSeriesGroupKeys) UniqueIdentifier() string { + sb := strings.Builder{} + for i, key := range s { + if i > 0 { + // add delimiter before index 1+ + sb.WriteString(";") + } + sb.WriteString(key.Encode()) + } + return sb.String() +} + +// CostSeriesGroupKey represents a grouping dimension for a cost series. +// If the group key is a tag, TagKey and TagValue are populated. +// Otherwise, Name is populated. +type CostSeriesGroupKey struct { + TagKey string `json:"tagKey,omitempty"` + TagValue string `json:"tagValue,omitempty"` + Name string `json:"name,omitempty"` +} + +// Encode creates a single string that can be decoded consistently +// We use `>` between tag key and tag value since it's an invalid character for aws tags, gcp labels, k8s labels, etc. +func (k CostSeriesGroupKey) Encode() string { + if k.TagKey != "" { + return fmt.Sprintf("%s$%s", k.TagKey, k.TagValue) + } + return k.Name +} + +// CostSeriesDatapoint represents a single datapoint in a cost series. +// It has a Start and End time to represent the time period covered by the datapoint. +// The Value is the cost for that period. +type CostSeriesDatapoint struct { + Start time.Time `json:"start"` + End time.Time `json:"end"` + Unit string `json:"unit"` + Value string `json:"value"` +} diff --git a/examples/aws/bootstrap/coster.go b/examples/aws/bootstrap/coster.go new file mode 100644 index 0000000..5ca131f --- /dev/null +++ b/examples/aws/bootstrap/coster.go @@ -0,0 +1,30 @@ +package bootstrap + +import ( + "encoding/json" + "os" + + "github.com/nullstone-io/infra-sdk/access/aws" + aws_account "github.com/nullstone-io/infra-sdk/builtin/aws/aws-account" + "gopkg.in/nullstone-io/go-api-client.v0/types" +) + +func NewCoster() (aws_account.Coster, error) { + credentials, _ := json.Marshal(types.AwsCredentials{ + AuthType: types.AwsAuthTypeAssumeRole, + AssumeRoleName: os.Getenv("AWS_ASSUME_ROLE_NAME"), + AssumeRoleExternalId: os.Getenv("AWS_ASSUME_ROLE_EXTERNAL_ID"), + }) + + return aws_account.Coster{ + Assumer: aws.Assumer{ + AccessKeyID: os.Getenv("ASSUMER_AWS_ACCESS_KEY_ID"), + SecretAccessKey: os.Getenv("ASSUMER_AWS_SECRET_ACCESS_KEY"), + }, + Provider: types.Provider{ + ProviderType: "aws", + ProviderId: os.Getenv("AWS_ACCOUNT_ID"), + Credentials: credentials, + }, + }, nil +} diff --git a/examples/aws/daily_by_env/main.go b/examples/aws/daily_by_env/main.go new file mode 100644 index 0000000..4f081d4 --- /dev/null +++ b/examples/aws/daily_by_env/main.go @@ -0,0 +1,49 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "log" + "os" + "os/signal" + "time" + + infra_sdk "github.com/nullstone-io/infra-sdk" + "github.com/nullstone-io/infra-sdk/examples/aws/bootstrap" +) + +// Month-to-date, daily, filtered to a single stack, grouped by env +func main() { + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill) + defer cancel() + + // Inputs + stacks := []string{"core"} + end := time.Now() + start := time.Date(end.Year(), end.Month(), 1, 0, 0, 0, 0, end.Location()) + + coster, err := bootstrap.NewCoster() + if err != nil { + log.Fatalln(err.Error()) + } + + query := infra_sdk.CostQuery{ + Start: start, + End: end, + Granularity: infra_sdk.CostGranularityDaily, + FilterTags: []infra_sdk.CostFilterTag{ + { + Key: infra_sdk.StandardTagStack, + Values: stacks, + }, + }, + GroupTags: []infra_sdk.CostGroupTag{{Key: infra_sdk.StandardTagEnv}}, + } + result, err := coster.GetCosts(ctx, query) + if err != nil { + log.Fatalln(err.Error()) + } + raw, _ := json.MarshalIndent(result, "", " ") + fmt.Println(string(raw)) +} diff --git a/examples/aws/daily_for_env_by_block/main.go b/examples/aws/daily_for_env_by_block/main.go new file mode 100644 index 0000000..1217418 --- /dev/null +++ b/examples/aws/daily_for_env_by_block/main.go @@ -0,0 +1,54 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "log" + "os" + "os/signal" + "time" + + infra_sdk "github.com/nullstone-io/infra-sdk" + "github.com/nullstone-io/infra-sdk/examples/aws/bootstrap" +) + +// Month-to-date, daily, filtered to a single stack, grouped by env +func main() { + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill) + defer cancel() + + // Inputs + stacks := []string{"core"} + envs := []string{"dev", "prod"} + end := time.Now() + start := time.Date(end.Year(), end.Month(), 1, 0, 0, 0, 0, end.Location()) + + coster, err := bootstrap.NewCoster() + if err != nil { + log.Fatalln(err.Error()) + } + + query := infra_sdk.CostQuery{ + Start: start, + End: end, + Granularity: infra_sdk.CostGranularityDaily, + FilterTags: []infra_sdk.CostFilterTag{ + { + Key: infra_sdk.StandardTagStack, + Values: stacks, + }, + { + Key: infra_sdk.StandardTagEnv, + Values: envs, + }, + }, + GroupTags: []infra_sdk.CostGroupTag{{Key: infra_sdk.StandardTagBlock}}, + } + result, err := coster.GetCosts(ctx, query) + if err != nil { + log.Fatalln(err.Error()) + } + raw, _ := json.MarshalIndent(result, "", " ") + fmt.Println(string(raw)) +} diff --git a/go.mod b/go.mod index c7e5a55..6ec2579 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.9 github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.9 github.com/aws/aws-sdk-go-v2/service/cloudfront v1.55.2 + github.com/aws/aws-sdk-go-v2/service/costexplorer v1.59.0 github.com/aws/aws-sdk-go-v2/service/ec2 v1.259.0 github.com/aws/aws-sdk-go-v2/service/ecs v1.66.0 github.com/aws/aws-sdk-go-v2/service/efs v1.41.0 @@ -24,14 +25,12 @@ require ( github.com/aws/aws-sdk-go-v2/service/sns v1.39.1 github.com/aws/aws-sdk-go-v2/service/sqs v1.42.11 github.com/aws/aws-sdk-go-v2/service/sts v1.38.9 - github.com/aws/smithy-go v1.23.1 golang.org/x/net v0.46.0 gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251028222640-d27c71d5cd3c ) require ( github.com/agext/levenshtein v1.2.3 // indirect - github.com/apparentlymart/go-textseg/v12 v12.0.0 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.2 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11 // indirect @@ -41,33 +40,18 @@ require ( github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.2 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.11 // indirect - github.com/cristalhq/jwt/v3 v3.1.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-logr/logr v1.4.3 // indirect - github.com/go-logr/stdr v1.2.2 // indirect + github.com/aws/smithy-go v1.23.1 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.5.3 // indirect github.com/hashicorp/hcl/v2 v2.24.0 // indirect github.com/jinzhu/copier v0.4.0 // indirect - github.com/kr/pretty v0.3.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/nullstone-io/module v0.2.10 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/spf13/afero v1.15.0 // indirect - github.com/stretchr/testify v1.11.1 // indirect github.com/tmccombs/hcl2json v0.6.8 // indirect github.com/zclconf/go-cty v1.17.0 // indirect - go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect - go.opentelemetry.io/otel v1.38.0 // indirect - go.opentelemetry.io/otel/metric v1.38.0 // indirect - go.opentelemetry.io/otel/trace v1.38.0 // indirect golang.org/x/mod v0.29.0 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/text v0.30.0 // indirect golang.org/x/tools v0.38.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index e7ce8eb..c65495e 100644 --- a/go.sum +++ b/go.sum @@ -1,150 +1,80 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= -github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= -github.com/apparentlymart/go-textseg/v12 v12.0.0 h1:bNEQyAGak9tojivJNkoqWErVCQbjdL7GzRt3F8NvfJ0= github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= -github.com/aws/aws-sdk-go-v2 v1.38.0 h1:UCRQ5mlqcFk9HJDIqENSLR3wiG1VTWlyUfLDEvY7RxU= -github.com/aws/aws-sdk-go-v2 v1.38.0/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= github.com/aws/aws-sdk-go-v2 v1.39.4 h1:qTsQKcdQPHnfGYBBs+Btl8QwxJeoWcOcPcixK90mRhg= github.com/aws/aws-sdk-go-v2 v1.39.4/go.mod h1:yWSxrnioGUZ4WVv9TgMrNUeLV3PFESn/v+6T/Su8gnM= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 h1:6GMWV6CNpA/6fbFHnoAjrv4+LGfyTqZz2LtCHnspgDg= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0/go.mod h1:/mXlTIVG9jbxkqDnr5UQNQxW1HRYxeGklkM9vAFeabg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.2 h1:t9yYsydLYNBk9cJ73rgPhPWqOh/52fcWDQB5b1JsKSY= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.2/go.mod h1:IusfVNTmiSN3t4rhxWFaBAqn+mcNdwKtPcV16eYdgko= -github.com/aws/aws-sdk-go-v2/credentials v1.18.4 h1:IPd0Algf1b+Qy9BcDp0sCUcIWdCQPSzDoMK3a8pcbUM= -github.com/aws/aws-sdk-go-v2/credentials v1.18.4/go.mod h1:nwg78FjH2qvsRM1EVZlX9WuGUJOL5od+0qvm0adEzHk= github.com/aws/aws-sdk-go-v2/credentials v1.18.19 h1:Jc1zzwkSY1QbkEcLujwqRTXOdvW8ppND3jRBb/VhBQc= github.com/aws/aws-sdk-go-v2/credentials v1.18.19/go.mod h1:DIfQ9fAk5H0pGtnqfqkbSIzky82qYnGvh06ASQXXg6A= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3 h1:o9RnO+YZ4X+kt5Z7Nvcishlz0nksIt2PIzDglLMP0vA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3/go.mod h1:+6aLJzOG1fvMOyzIySYjOFjcguGvVRL68R+uoRencN4= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11 h1:7AANQZkF3ihM8fbdftpjhken0TP9sBzFbV/Ze/Y4HXA= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11/go.mod h1:NTF4QCGkm6fzVwncpkFQqoquQyOolcyXfbpC98urj+c= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3 h1:joyyUFhiTQQmVK6ImzNU9TQSNRNeD9kOklqTzyk5v6s= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3/go.mod h1:+vNIyZQP3b3B1tSLI0lxvrU9cfM7gpdRXMFfm67ZcPc= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.11 h1:ShdtWUZT37LCAA4Mw2kJAJtzaszfSHFb5n25sdcv4YE= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.11/go.mod h1:7bUb2sSr2MZ3M/N+VyETLTQtInemHXb/Fl3s8CLzm0Y= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3 h1:ZV2XK2L3HBq9sCKQiQ/MdhZJppH/rH0vddEAamsHUIs= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.3/go.mod h1:b9F9tk2HdHpbf3xbN7rUZcfmJI26N6NcJu/8OsBFI/0= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.11 h1:bKgSxk1TW//00PGQqYmrq83c+2myGidEclp+t9pPqVI= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.11/go.mod h1:vrPYCQ6rFHL8jzQA8ppu3gWX18zxjLIDGTeqDxkBmSI= -github.com/aws/aws-sdk-go-v2/service/apigateway v1.34.0 h1:IZAET61abhm3dZEMPwU6VLiXKVL2Qwvg0q7Bukpz/kA= -github.com/aws/aws-sdk-go-v2/service/apigateway v1.34.0/go.mod h1:WuGmD7SWYen7UZcDGptMvzl6bN5OZ1x+Io1eI5XN7kU= github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.9 h1:9izRfGPf77V364SWt2NjmR/3VI7AgRAFZaDJHAtD9pI= github.com/aws/aws-sdk-go-v2/service/apigateway v1.35.9/go.mod h1:/a0evDW8qp3FPS7HxI+dG2u0K/9sdr3NBI1tiP5ViiU= -github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.31.0 h1:bbHfZmF4H/PG5EEo0hXDyM/45XZDMbkscXolqardpB0= -github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.31.0/go.mod h1:qlUNYJtHoTWiJQMJkgi93jwRNRt9uIOUSMZrwMODh7Y= github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.9 h1:sMk/ugu7Ct4Zd/98Toofflm15Jpt+1ZVDxP1BhuhnEY= github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.32.9/go.mod h1:aoFp4iEj5JG8/AssywlKPoFUBfsoLDM04/Q92ADm3Z0= -github.com/aws/aws-sdk-go-v2/service/cloudfront v1.52.0 h1:rJcbtmScByQ6NBIXV97m6e8Rasd0zgvt1z84pdddU/4= -github.com/aws/aws-sdk-go-v2/service/cloudfront v1.52.0/go.mod h1:qTc2+9g3YGM5d/u+c4tmHun6vmEKwBjJ7rEM6N3qGVI= github.com/aws/aws-sdk-go-v2/service/cloudfront v1.55.2 h1:MnDEmZz8maF6Ge2GaK6T16jqPDhyesUODhMheFqUBqU= github.com/aws/aws-sdk-go-v2/service/cloudfront v1.55.2/go.mod h1:Ql3i8VKmdfYCcDhG6OpVkGM60IN9fPDV/7aMHCH3lds= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.243.0 h1:s7mU5Zfa1ksg86BGjYKU03Bs63m5MY1ps4jOZFayBwM= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.243.0/go.mod h1:EeWmteKqZjaMj45MUmPET1SisFI+HkqWIRQoyjMivcc= +github.com/aws/aws-sdk-go-v2/service/costexplorer v1.59.0 h1:yQ/svgYI6tBCp8tK6Z1CCBcyVAAN+VV1uOdtqUaCLP8= +github.com/aws/aws-sdk-go-v2/service/costexplorer v1.59.0/go.mod h1:lztpwJzFHVpn5pcUzSh4bvHwvOz9Tya+MzN84KluABA= github.com/aws/aws-sdk-go-v2/service/ec2 v1.259.0 h1:0BwB+z9JX7fleVvaZaUuzIHvGWiWn2BQLJIW2riEzDQ= github.com/aws/aws-sdk-go-v2/service/ec2 v1.259.0/go.mod h1:DT0XByGaNaOff3CtLVmj3jKcMeVDfOj5DkLD39UPJY0= -github.com/aws/aws-sdk-go-v2/service/ecs v1.63.0 h1:ZeUDPcF93I5pE614AD8Le5a1e+383jjJ8lopM/WVfB8= -github.com/aws/aws-sdk-go-v2/service/ecs v1.63.0/go.mod h1:k5xD9wMxhUgcFU0Q1F1iB3YJkmBmW7+o4rrsBg8yhdc= github.com/aws/aws-sdk-go-v2/service/ecs v1.66.0 h1:+apffrlIoVKFtykMzQx9wn4Uk3Qjyrwq8kqubh0TOpA= github.com/aws/aws-sdk-go-v2/service/ecs v1.66.0/go.mod h1:E9n0AAMdcWJ66TGaYOb9SeDDQKG8dYuftwJSt+v6cHg= -github.com/aws/aws-sdk-go-v2/service/efs v1.39.0 h1:nxn7P1nAd7ThB1B0WASAKvjddJQcvLzaOo9iN4tp3ZU= -github.com/aws/aws-sdk-go-v2/service/efs v1.39.0/go.mod h1:8Ij4/TIExqfWWjcyQy82/V/aec2kQruuyndljE+Vuo0= github.com/aws/aws-sdk-go-v2/service/efs v1.41.0 h1:OR1o4u/nIvqv+jsZ8H3eHXi/dSYCz7LldGqkq0Ackmo= github.com/aws/aws-sdk-go-v2/service/efs v1.41.0/go.mod h1:lFDyqDkf31PrYYD4ovdvRSDfMHmNc+vYrd6pgpFvQvk= -github.com/aws/aws-sdk-go-v2/service/elasticache v1.49.0 h1:zJY3lR0AdRuigAub2GQkIMz/TP50Ia6R6VruPgWBIxk= -github.com/aws/aws-sdk-go-v2/service/elasticache v1.49.0/go.mod h1:CeEl4WwCPhtncasl9kdhSp1rigeO3HdVJ3hiPu6ZdZI= github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.8 h1:qXfdy9KaBDV4XhAvkMXRuDNPR5BOWNh/d4mrsERRWg8= github.com/aws/aws-sdk-go-v2/service/elasticache v1.50.8/go.mod h1:uiPTYuaQyaWsPvH45Pae/8gA3o8i6QLFVj8B/FaD6BQ= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.32.0 h1:FO6LzHczDXByBf8+WJ5cswxaGy1EOjDVXA3NQa97Bh8= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.32.0/go.mod h1:q2K5uszrJv1SBxKYp5M9KUf7XR/Xnu38vSCiQ/wwhfI= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.9 h1:FqNGRAEtxCVek0rkz8rbxjqQu+yCdPsgQpBHbqoT6oE= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.9/go.mod h1:Oc5IwJcGA5MlCZcn2v9u5ke2D2TuST7tCDhKYup6DB8= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.49.0 h1:2VJj7fSoDawAjQ91u/DtrrUDOGsuMaWxcbe9Ok/O27w= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.49.0/go.mod h1:vJgvNz01VmSuXKzoUwQxQCzYklI/f09wXCWoj6TBGJE= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.51.3 h1:xKXVGDuAA1teDKhga/ds3N+pQkbcq9ON3RnnEhXnOdw= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.51.3/go.mod h1:gKD1BXAg9fRSxeFlSYkYEO3uxfhNXUyrtXUUDoc7WSI= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2 h1:xtuxji5CS0JknaXoACOunXOYOQzgfTvGAc9s2QdCJA4= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2/go.mod h1:zxwi0DIR0rcRcgdbl7E2MSOvxDyyXGBlScvBkARFaLQ= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3 h1:3ZKmesYBaFX33czDl6mbrcHb6jeheg6LqjJhQdefhsY= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.3/go.mod h1:7ryVb78GLCnjq7cw45N6oUb9REl7/vNUwjvIqC5UgdY= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.2 h1:DGFpGybmutVsCuF6vSuLZ25Vh55E3VmsnJmFfjeBx4M= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.2/go.mod h1:hm/wU1HDvXCFEDzOLorQnZZ/CVvPXvWEmHMSmqgQRuA= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3 h1:ieRzyHXypu5ByllM7Sp4hC5f/1Fy5wqxqY0yB85hC7s= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3/go.mod h1:O5ROz8jHiOAKAwx179v+7sHMhfobFVi6nZt8DEyiYoM= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11 h1:GpMf3z2KJa4RnJ0ew3Hac+hRFYLZ9DDjfgXjuW+pB54= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11/go.mod h1:6MZP3ZI4QQsgUCFTwMZA2V0sEriNQ8k2hmoHF3qjimQ= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3 h1:SE/e52dq9a05RuxzLcjT+S5ZpQobj3ie3UTaSf2NnZc= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.3/go.mod h1:zkpvBTsR020VVr8TOrwK2TrUW9pOir28sH5ECHpnAfo= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.11 h1:weapBOuuFIBEQ9OX/NVW3tFQCvSutyjZYk/ga5jDLPo= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.11/go.mod h1:3C1gN4FmIVLwYSh8etngUS+f1viY6nLCDVtZmrFbDy0= -github.com/aws/aws-sdk-go-v2/service/kafka v1.42.0 h1:/EB9p30Te0eClIIptu3g3meO38O87YVVdE/UVbyTvWA= -github.com/aws/aws-sdk-go-v2/service/kafka v1.42.0/go.mod h1:uvEnl4e5ie3zB+2qlQCqcv0CgOyI8ajOegLEKERjqfs= github.com/aws/aws-sdk-go-v2/service/kafka v1.44.1 h1:7pL53Xx0y+U6QTnDig6lEstKPie4yFkzDwm/xlv8jVw= github.com/aws/aws-sdk-go-v2/service/kafka v1.44.1/go.mod h1:wcD5HEMcPgVNbIKhL/Q07FFtsCt+30WtvUqbA5OVdpU= -github.com/aws/aws-sdk-go-v2/service/mq v1.32.0 h1:h04Kq2u2B6bDeAmNoxlf9bqtKH3GUlkW3p/+e/mE7+o= -github.com/aws/aws-sdk-go-v2/service/mq v1.32.0/go.mod h1:tVSPpsQhalaf+DchZKFeDoohUeNE8dVSFGNRjZrDSQE= github.com/aws/aws-sdk-go-v2/service/mq v1.34.6 h1:/LZXn/hzI14D04Zl7j3wDQpQmQx9UGqwnKLwKlRKZaY= github.com/aws/aws-sdk-go-v2/service/mq v1.34.6/go.mod h1:CK40LT9yOzs/YJ8w46mp2pWBMkduiMdkDr/dO2FrUyU= -github.com/aws/aws-sdk-go-v2/service/opensearch v1.51.0 h1:dxYQ9hDRI/yXFzO3sYT+x3Ss2d8JDf2eX5hyUPHG6fA= -github.com/aws/aws-sdk-go-v2/service/opensearch v1.51.0/go.mod h1:NQvq4ckAgpR9/QqqI5+eWnP6rNlpOVta9udBG9GVHcw= github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.8 h1:lFeAFG+OOMbUFcTgsROi1uIjOOCLA6pWAgL4SfTiGBY= github.com/aws/aws-sdk-go-v2/service/opensearch v1.52.8/go.mod h1:Vl3ROh8aYzg2O8dqmT+vQ0K9bIMoZMkWYl0BzYctlSg= -github.com/aws/aws-sdk-go-v2/service/rds v1.103.0 h1:OWsmICx9jHtBVrgYwYb+2q0iVSPLIfDZOiKhoQA+gjc= -github.com/aws/aws-sdk-go-v2/service/rds v1.103.0/go.mod h1:tUKTkGAlJo0Gs4t0Z46vaSGD6H1Z6RvtuF03mZY+tPk= github.com/aws/aws-sdk-go-v2/service/rds v1.108.5 h1:Rxc/LXqxopzlCJATNOdaJ4pDCcLCOEYz+qJv2RagYho= github.com/aws/aws-sdk-go-v2/service/rds v1.108.5/go.mod h1:9wC1x+2lS3i2HgPfkabhzms6Hga49X+lOUTppHnhJgM= -github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.29.0 h1:jevrLpVG9sOEPsuipO3eGcdDzJyo36Dmme9iSu/8GVE= -github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.29.0/go.mod h1:t/zZb99l0WrcNYbDIF3tgj0rJNklhiVa6B1x/Rz4rHc= github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.9 h1:x4J04vxdladHgy+ZPsYbgZ3B6KDeIzYvGbnFOMu3DjE= github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.30.9/go.mod h1:XDxyme5t2QvddctkZPZPHhjf0sMIO+unwz1nXg8pYOI= -github.com/aws/aws-sdk-go-v2/service/route53 v1.56.1 h1:EqIPe7aD4cdk0xJINBhnxmifR/+T5TuXIHn2ivu8zKQ= -github.com/aws/aws-sdk-go-v2/service/route53 v1.56.1/go.mod h1:aSIshIhq15I4lMlrkvvIoH7E4eLTAEW+isWbga9guNg= github.com/aws/aws-sdk-go-v2/service/route53 v1.59.1 h1:KuoA/cmy/yK8n9v/d6WH36cZwGxFOrn0TmZ4lNN3MKQ= github.com/aws/aws-sdk-go-v2/service/route53 v1.59.1/go.mod h1:BymbICXBfXQHO6i+yTBhocA9a6DM0uMDQqYelqa9wzs= -github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0 h1:egoDf+Geuuntmw79Mz6mk9gGmELCPzg5PFEABOHB+6Y= -github.com/aws/aws-sdk-go-v2/service/s3 v1.87.0/go.mod h1:t9MDi29H+HDbkolTSQtbI0HP9DemAWQzUjmWC7LGMnE= github.com/aws/aws-sdk-go-v2/service/s3 v1.89.0 h1:JbCUlVDEjmhpvpIgXP9QN+/jW61WWWj99cGmxMC49hM= github.com/aws/aws-sdk-go-v2/service/s3 v1.89.0/go.mod h1:UHKgcRSx8PVtvsc1Poxb/Co3PD3wL7P+f49P0+cWtuY= -github.com/aws/aws-sdk-go-v2/service/sns v1.37.0 h1:+GWmgZ6TeJ12tLw4l981+5nc9FDdzXtdZlnmp6KVHig= -github.com/aws/aws-sdk-go-v2/service/sns v1.37.0/go.mod h1:O4eFpSa/AodvDLJqarL+0vnRgDP9d/FEKHZmzLnA/1c= github.com/aws/aws-sdk-go-v2/service/sns v1.39.1 h1:GKg/7I4IGRrAm0j5Hwxrk8B9LXhzfxyDoDazW5XB7Ew= github.com/aws/aws-sdk-go-v2/service/sns v1.39.1/go.mod h1:jQSGNtQAakrW+5vvUF5398mxsHryy0rsYWUXIQoHDAw= -github.com/aws/aws-sdk-go-v2/service/sqs v1.41.0 h1:xobvQ4NxlXFUNgVwE6cnMI/ww7K7jtQMWKor2Gi61Xg= -github.com/aws/aws-sdk-go-v2/service/sqs v1.41.0/go.mod h1:RExz4LhRKY5iogQ1dz7KVa3JyBY0PBotXovrDj850Sc= github.com/aws/aws-sdk-go-v2/service/sqs v1.42.11 h1:tt34G790giMoWqpqJOfvc5BD25hHRSjgvx1x1jtwi9w= github.com/aws/aws-sdk-go-v2/service/sqs v1.42.11/go.mod h1:tj8YTswoacIeRGjkYuHOkUd4ioQ4Of0m+gy09kuns9o= -github.com/aws/aws-sdk-go-v2/service/sts v1.37.0 h1:MG9VFW43M4A8BYeAfaJJZWrroinxeTi2r3+SnmLQfSA= -github.com/aws/aws-sdk-go-v2/service/sts v1.37.0/go.mod h1:JdeBDPgpJfuS6rU/hNglmOigKhyEZtBmbraLE4GK1J8= github.com/aws/aws-sdk-go-v2/service/sts v1.38.9 h1:Ekml5vGg6sHSZLZJQJagefnVe6PmqC2oiRkBq4F7fU0= github.com/aws/aws-sdk-go-v2/service/sts v1.38.9/go.mod h1:/e15V+o1zFHWdH3u7lpI3rVBcxszktIKuHKCY2/py+k= -github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw= -github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/aws/smithy-go v1.23.1 h1:sLvcH6dfAFwGkHLZ7dGiYF7aK6mg4CgKA/iDKjLDt9M= github.com/aws/smithy-go v1.23.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cristalhq/jwt/v3 v3.1.0 h1:iLeL9VzB0SCtjCy9Kg53rMwTcrNm+GHyVcz2eUujz6s= -github.com/cristalhq/jwt/v3 v3.1.0/go.mod h1:XOnIXst8ozq/esy5N1XOlSyQqBd+84fxJ99FK+1jgL8= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= +github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= @@ -153,50 +83,32 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= -github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/hcl/v2 v2.6.0 h1:3krZOfGY6SziUXa6H9PJU6TyohHn7I+ARYnhbeNBz+o= github.com/hashicorp/hcl/v2 v2.6.0/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY= github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQxvE= github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= -github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/nullstone-io/module v0.2.10 h1:wCKrlyxyH9XQW5HliW/V6qNsDgUQxUCcWL60Ojlz+2U= github.com/nullstone-io/module v0.2.10/go.mod h1:btQiO0giVWDvvaQ7CLnPmuPPakJc55lAr8OlE1LK6hg= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/tmccombs/hcl2json v0.3.2-0.20201111174327-c96737926b76 h1:fUns9d7I0QAm9xW/xVgtys0B0UplMuopZHgKQEE+nrc= github.com/tmccombs/hcl2json v0.3.2-0.20201111174327-c96737926b76/go.mod h1:ljY0/prd2IFUF3cagQjV3cpPEEQKzqyGqnKI7m5DBVY= github.com/tmccombs/hcl2json v0.6.8 h1:9bd7c3jZTj9FsN+lDIzrvLmXqxvCgydb84Uc4DBxOHA= github.com/tmccombs/hcl2json v0.6.8/go.mod h1:qjEaQ4hBNPeDWOENB9yg6+BzqvtMA1MMN1+goFFh8Vc= @@ -205,30 +117,18 @@ github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6Ac github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= -github.com/zclconf/go-cty v1.6.1 h1:wHtZ+LSSQVwUSb+XIJ5E9hgAQxyWATZsAWT+ESJ9dQ0= github.com/zclconf/go-cty v1.6.1/go.mod h1:VDR4+I79ubFBGm1uJac1226K5yANQFHeauxPBoP54+o= github.com/zclconf/go-cty v1.17.0 h1:seZvECve6XX4tmnvRzWtJNHdscMtYEx5R7bnnVyd/d0= github.com/zclconf/go-cty v1.17.0/go.mod h1:wqFzcImaLTI6A5HfsRwB0nj5n0MRZFwmey8YoFPPs3U= -go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= -go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= -go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= -go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= -go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= -go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= -go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= -go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= -golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= @@ -240,8 +140,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -251,8 +149,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20250814151520-6962f4e47dd6 h1:+OMGXr7B93pg98thoBBf01sFkkFYJ7Vl0iVUXqqVZOI= -gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20250814151520-6962f4e47dd6/go.mod h1:JE4cnrQcRkYZtl5HWkwJ2S4Oep8d1iv6lYQRQ5BC7cU= gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251028222640-d27c71d5cd3c h1:0tx+r3tgGorPT6EWXawRiT3PFi5GBPMW1OIuc6kW+9U= gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251028222640-d27c71d5cd3c/go.mod h1:Bj01hknD135uWb7j+9EIcE775ZXYv9pWSXdryTHMrhM= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/standard_tags.go b/standard_tags.go new file mode 100644 index 0000000..607b1e9 --- /dev/null +++ b/standard_tags.go @@ -0,0 +1,33 @@ +package infra_sdk + +const ( + StandardTagStack = "nullstone.io/stack" + StandardTagEnv = "nullstone.io/env" + StandardTagBlock = "nullstone.io/block" +) + +// MapStandardTagToLegacy maps the standard tag keys to ones that every Nullstone module contains +// Eventually, the Nullstone modules will use the standard tag keys instead +func MapStandardTagToLegacy(input string) string { + switch input { + case StandardTagStack: + return "Stack" + case StandardTagEnv: + return "Env" + case StandardTagBlock: + return "Block" + } + return input +} + +func MapLegacyTagToStandard(input string) string { + switch input { + case "Stack": + return StandardTagStack + case "Env": + return StandardTagEnv + case "Block": + return StandardTagBlock + } + return input +} From b776c7f8efdd1f73af1d8f38166b81d3bee07a65 Mon Sep 17 00:00:00 2001 From: Brad Sickles Date: Thu, 30 Oct 2025 11:23:59 -0400 Subject: [PATCH 3/9] simplify coster/scanner factory --- builtin/coster_creator.go | 32 ++++++++++++++++++++++++++++++++ builtin/scanner_creator.go | 34 ++++++++-------------------------- coster.go | 2 +- 3 files changed, 41 insertions(+), 27 deletions(-) create mode 100644 builtin/coster_creator.go diff --git a/builtin/coster_creator.go b/builtin/coster_creator.go new file mode 100644 index 0000000..a81a085 --- /dev/null +++ b/builtin/coster_creator.go @@ -0,0 +1,32 @@ +package builtin + +import ( + "context" + + infra_sdk "github.com/nullstone-io/infra-sdk" + "github.com/nullstone-io/infra-sdk/access/aws" + aws_account "github.com/nullstone-io/infra-sdk/builtin/aws/aws-account" + "gopkg.in/nullstone-io/go-api-client.v0/types" +) + +type CosterCreator struct { + AwsAssumer aws.Assumer +} + +func (s CosterCreator) NewCoster(ctx context.Context, getProviderFn GetProviderFunc, orgName string, providerConfig types.ProviderConfig) (infra_sdk.Coster, error) { + if providerConfig.Aws != nil && providerConfig.Aws.ProviderName != "" { + provider, err := getProviderFn(ctx, orgName, providerConfig.Aws.ProviderName) + if err != nil { + return nil, err + } else if provider != nil { + return aws_account.Coster{ + Assumer: s.AwsAssumer, + Provider: *provider, + }, nil + } + } + if providerConfig.Gcp != nil { + // TODO: Implement GCP + } + return nil, nil +} diff --git a/builtin/scanner_creator.go b/builtin/scanner_creator.go index 2cbd1d8..a7ba84b 100644 --- a/builtin/scanner_creator.go +++ b/builtin/scanner_creator.go @@ -2,6 +2,7 @@ package builtin import ( "context" + infra_sdk "github.com/nullstone-io/infra-sdk" "github.com/nullstone-io/infra-sdk/access/aws" aws_account "github.com/nullstone-io/infra-sdk/builtin/aws/aws-account" @@ -15,39 +16,20 @@ type ScannerCreator struct { } func (s ScannerCreator) NewScanner(ctx context.Context, getProviderFn GetProviderFunc, orgName string, providerConfig types.ProviderConfig) (infra_sdk.Scanner, error) { - scanner := MultiScanner{Scanners: make([]infra_sdk.Scanner, 0)} - if providerConfig.Aws != nil { + if providerConfig.Aws != nil && providerConfig.Aws.ProviderName != "" { provider, err := getProviderFn(ctx, orgName, providerConfig.Aws.ProviderName) if err != nil { return nil, err + } else if provider != nil { + return aws_account.Scanner{ + Assumer: s.AwsAssumer, + Provider: *provider, + ProviderConfig: providerConfig, + }, nil } - scanner.Scanners = append(scanner.Scanners, aws_account.Scanner{ - Assumer: s.AwsAssumer, - Provider: *provider, - ProviderConfig: providerConfig, - }) } if providerConfig.Gcp != nil { // TODO: Implement GCP } - return scanner, nil -} - -var ( - _ infra_sdk.Scanner = MultiScanner{} -) - -type MultiScanner struct { - Scanners []infra_sdk.Scanner -} - -func (s MultiScanner) Scan(ctx context.Context) ([]infra_sdk.ScanResource, error) { - for _, scanner := range s.Scanners { - resources, err := scanner.Scan(ctx) - if err != nil { - return nil, err - } - return resources, nil - } return nil, nil } diff --git a/coster.go b/coster.go index b257a4e..20070f7 100644 --- a/coster.go +++ b/coster.go @@ -16,7 +16,7 @@ const ( ) type Coster interface { - GetCosts(ctx context.Context, query CostQuery) (CostResult, error) + GetCosts(ctx context.Context, query CostQuery) (*CostResult, error) } type CostQuery struct { From 6481ac4e070ac44e89fde61b93054cdbf018718b Mon Sep 17 00:00:00 2001 From: Brad Sickles Date: Thu, 6 Nov 2025 12:09:42 -0500 Subject: [PATCH 4/9] universal tags/dimensions, added support to group aws dimensions --- .../aws/aws-account/cost_result_aggregator.go | 21 +++++--- builtin/aws/aws-account/coster.go | 41 ++++++++------- builtin/aws/aws-account/universal_names.go | 51 +++++++++++++++++++ coster.go | 51 ++++++++++++++----- examples/aws/daily_by_env/main.go | 7 ++- examples/aws/daily_for_env_by_block/main.go | 9 ++-- standard_tags.go | 33 ------------ universal_names.go | 9 ++++ 8 files changed, 143 insertions(+), 79 deletions(-) create mode 100644 builtin/aws/aws-account/universal_names.go delete mode 100644 standard_tags.go create mode 100644 universal_names.go diff --git a/builtin/aws/aws-account/cost_result_aggregator.go b/builtin/aws/aws-account/cost_result_aggregator.go index 4bf0097..965ad70 100644 --- a/builtin/aws/aws-account/cost_result_aggregator.go +++ b/builtin/aws/aws-account/cost_result_aggregator.go @@ -20,7 +20,7 @@ type CostResultAggregator struct { CostResult *infra_sdk.CostResult } -func (a *CostResultAggregator) AddResults(resultsByTime []cetypes.ResultByTime) error { +func (a *CostResultAggregator) AddResults(resultsByTime []cetypes.ResultByTime, inputGroups infra_sdk.CostGroupIdentifiers) error { for _, resultByTime := range resultsByTime { start, end, err := a.parseWindow(resultByTime) if err != nil { @@ -28,7 +28,7 @@ func (a *CostResultAggregator) AddResults(resultsByTime []cetypes.ResultByTime) } for _, grp := range resultByTime.Groups { - grpKeys := a.parseResultGroupKeys(grp.Keys) + grpKeys := a.parseResultGroupKeys(inputGroups, grp.Keys) for metricName, metricValue := range grp.Metrics { a.CostResult.AddDatapoint(metricName, grpKeys, infra_sdk.CostSeriesDatapoint{ Start: start, @@ -58,19 +58,26 @@ func (a *CostResultAggregator) parseWindow(resultByTime cetypes.ResultByTime) (t return start, end, nil } -func (a *CostResultAggregator) parseResultGroupKeys(keys []string) infra_sdk.CostSeriesGroupKeys { +func (a *CostResultAggregator) parseResultGroupKeys(inputGroups infra_sdk.CostGroupIdentifiers, keys []string) infra_sdk.CostSeriesGroupKeys { sort.Strings(keys) result := make(infra_sdk.CostSeriesGroupKeys, 0) - for _, key := range keys { + for i, key := range keys { tokens := strings.SplitN(key, "$", 2) if len(tokens) == 2 { result = append(result, infra_sdk.CostSeriesGroupKey{ - TagKey: infra_sdk.MapLegacyTagToStandard(tokens[0]), - TagValue: tokens[1], + TagKey: AwsTag(tokens[0]).ToUniversal(), + Value: tokens[1], }) } else { - result = append(result, infra_sdk.CostSeriesGroupKey{Name: key}) + name := fmt.Sprintf("dimension-%d", i) + if i < len(inputGroups) { + name = inputGroups[i].Dimension + } + result = append(result, infra_sdk.CostSeriesGroupKey{ + Name: name, + Value: key, + }) } } return result diff --git a/builtin/aws/aws-account/coster.go b/builtin/aws/aws-account/coster.go index e9e9f9e..8b7f7cf 100644 --- a/builtin/aws/aws-account/coster.go +++ b/builtin/aws/aws-account/coster.go @@ -45,12 +45,13 @@ func (c Coster) GetCosts(ctx context.Context, query infra_sdk.CostQuery) (*infra granularity = cetypes.GranularityDaily } + groupBy := query.GroupBy.Unique() input := &ce.GetCostAndUsageInput{ TimePeriod: period, Granularity: granularity, Metrics: []string{"UnblendedCost"}, Filter: costQueryToFilter(query), - GroupBy: costQueryToGroupBy(query), + GroupBy: costQueryToGroupBy(groupBy), } rawInput, _ := json.Marshal(input) log.Println("input", string(rawInput)) @@ -63,7 +64,7 @@ func (c Coster) GetCosts(ctx context.Context, query infra_sdk.CostQuery) (*infra if err != nil { return nil, fmt.Errorf("error querying aws cost explorer: %w", err) } - if err := aggregator.AddResults(out.ResultsByTime); err != nil { + if err := aggregator.AddResults(out.ResultsByTime, groupBy); err != nil { return nil, fmt.Errorf("error aggregating results: %w", err) } if out.NextPageToken == nil || *out.NextPageToken == "" { @@ -82,7 +83,7 @@ func costQueryToFilter(query infra_sdk.CostQuery) *cetypes.Expression { if len(query.FilterTags) == 1 { return &cetypes.Expression{ Tags: &cetypes.TagValues{ - Key: ptr(infra_sdk.MapStandardTagToLegacy(query.FilterTags[0].Key)), + Key: ptr(UniversalTag(query.FilterTags[0].Key).ToAws()), MatchOptions: []cetypes.MatchOption{cetypes.MatchOptionEquals}, Values: query.FilterTags[0].Values, }, @@ -93,7 +94,7 @@ func costQueryToFilter(query infra_sdk.CostQuery) *cetypes.Expression { for _, filterTag := range query.FilterTags { root.And = append(root.And, cetypes.Expression{ Tags: &cetypes.TagValues{ - Key: ptr(infra_sdk.MapStandardTagToLegacy(filterTag.Key)), + Key: ptr(UniversalTag(filterTag.Key).ToAws()), MatchOptions: []cetypes.MatchOption{cetypes.MatchOptionEquals}, Values: filterTag.Values, }, @@ -102,23 +103,21 @@ func costQueryToFilter(query infra_sdk.CostQuery) *cetypes.Expression { return root } -func costQueryToGroupBy(query infra_sdk.CostQuery) []cetypes.GroupDefinition { - if len(query.GroupTags) < 1 { - return nil - } - - // Don't allow duplicate group tags - unique := map[string]bool{} - for _, groupTag := range query.GroupTags { - unique[infra_sdk.MapStandardTagToLegacy(groupTag.Key)] = true - } +func costQueryToGroupBy(groupBy infra_sdk.CostGroupIdentifiers) []cetypes.GroupDefinition { + var defs []cetypes.GroupDefinition + for _, cur := range groupBy { + if cur.Dimension != "" { + defs = append(defs, cetypes.GroupDefinition{ + Key: ptr(UniversalDimension(cur.Dimension).ToAws()), + Type: cetypes.GroupDefinitionTypeDimension, + }) + } else if cur.TagKey != "" { + defs = append(defs, cetypes.GroupDefinition{ + Key: ptr(UniversalTag(cur.TagKey).ToAws()), + Type: cetypes.GroupDefinitionTypeTag, + }) + } - var groupBy []cetypes.GroupDefinition - for key := range unique { - groupBy = append(groupBy, cetypes.GroupDefinition{ - Key: ptr(key), - Type: cetypes.GroupDefinitionTypeTag, - }) } - return groupBy + return defs } diff --git a/builtin/aws/aws-account/universal_names.go b/builtin/aws/aws-account/universal_names.go new file mode 100644 index 0000000..1f0868d --- /dev/null +++ b/builtin/aws/aws-account/universal_names.go @@ -0,0 +1,51 @@ +package aws_account + +import infra_sdk "github.com/nullstone-io/infra-sdk" + +type AwsDimension string + +func (d AwsDimension) ToUniversal() string { + switch d { + case "LINKED_ACCOUNT": + return infra_sdk.UniversalDimensionAccount + } + return string(d) +} + +type UniversalDimension string + +func (d UniversalDimension) ToAws() string { + switch d { + case infra_sdk.UniversalDimensionAccount: + return "LINKED_ACCOUNT" + } + return string(d) +} + +type AwsTag string + +func (t AwsTag) ToUniversal() string { + switch t { + case "Stack": + return infra_sdk.UniversalTagStack + case "Env": + return infra_sdk.UniversalTagEnv + case "Block": + return infra_sdk.UniversalTagBlock + } + return string(t) +} + +type UniversalTag string + +func (t UniversalTag) ToAws() string { + switch t { + case infra_sdk.UniversalTagStack: + return "Stack" + case infra_sdk.UniversalTagEnv: + return "Env" + case infra_sdk.UniversalTagBlock: + return "Block" + } + return string(t) +} diff --git a/coster.go b/coster.go index 20070f7..36a6367 100644 --- a/coster.go +++ b/coster.go @@ -20,11 +20,11 @@ type Coster interface { } type CostQuery struct { - Start time.Time `json:"start"` - End time.Time `json:"end"` - Granularity CostGranularity `json:"granularity"` - FilterTags []CostFilterTag `json:"filterTags"` - GroupTags []CostGroupTag `json:"groupTags"` + Start time.Time `json:"start"` + End time.Time `json:"end"` + Granularity CostGranularity `json:"granularity"` + FilterTags []CostFilterTag `json:"filterTags"` + GroupBy CostGroupIdentifiers `json:"groupBy"` } type CostFilterTag struct { @@ -32,8 +32,33 @@ type CostFilterTag struct { Values []string `json:"values"` } -type CostGroupTag struct { - Key string `json:"key"` +type CostGroupIdentifiers []CostGroupIdentifier + +func (s CostGroupIdentifiers) Unique() CostGroupIdentifiers { + result := make(CostGroupIdentifiers, 0) + + visitedTags := map[string]bool{} + visitedDimensions := map[string]bool{} + for _, cur := range s { + if cur.TagKey != "" { + if _, visited := visitedTags[cur.TagKey]; !visited { + result = append(result, cur) + visitedTags[cur.TagKey] = true + } + } else if cur.Dimension != "" { + if _, visited := visitedDimensions[cur.Dimension]; !visited { + result = append(result, cur) + visitedDimensions[cur.Dimension] = true + } + } + } + + return result +} + +type CostGroupIdentifier struct { + TagKey string `json:"tagKey,omitempty"` + Dimension string `json:"dimension,omitempty"` } type CostResult struct { @@ -84,18 +109,18 @@ func (s CostSeriesGroupKeys) UniqueIdentifier() string { // If the group key is a tag, TagKey and TagValue are populated. // Otherwise, Name is populated. type CostSeriesGroupKey struct { - TagKey string `json:"tagKey,omitempty"` - TagValue string `json:"tagValue,omitempty"` - Name string `json:"name,omitempty"` + Name string `json:"name"` + TagKey string `json:"tagKey"` + Value string `json:"value"` } // Encode creates a single string that can be decoded consistently -// We use `>` between tag key and tag value since it's an invalid character for aws tags, gcp labels, k8s labels, etc. +// We use `>` between name/tag-key and value since it's an invalid character for aws tags, gcp labels, k8s labels, etc. func (k CostSeriesGroupKey) Encode() string { if k.TagKey != "" { - return fmt.Sprintf("%s$%s", k.TagKey, k.TagValue) + return fmt.Sprintf("%s$%s", k.TagKey, k.Value) } - return k.Name + return fmt.Sprintf("%s$%s", k.Name, k.Value) } // CostSeriesDatapoint represents a single datapoint in a cost series. diff --git a/examples/aws/daily_by_env/main.go b/examples/aws/daily_by_env/main.go index 4f081d4..3acae3d 100644 --- a/examples/aws/daily_by_env/main.go +++ b/examples/aws/daily_by_env/main.go @@ -34,11 +34,14 @@ func main() { Granularity: infra_sdk.CostGranularityDaily, FilterTags: []infra_sdk.CostFilterTag{ { - Key: infra_sdk.StandardTagStack, + Key: infra_sdk.UniversalTagStack, Values: stacks, }, }, - GroupTags: []infra_sdk.CostGroupTag{{Key: infra_sdk.StandardTagEnv}}, + GroupBy: infra_sdk.CostGroupIdentifiers{ + {Dimension: infra_sdk.UniversalDimensionAccount}, + {TagKey: infra_sdk.UniversalTagEnv}, + }, } result, err := coster.GetCosts(ctx, query) if err != nil { diff --git a/examples/aws/daily_for_env_by_block/main.go b/examples/aws/daily_for_env_by_block/main.go index 1217418..e349d8c 100644 --- a/examples/aws/daily_for_env_by_block/main.go +++ b/examples/aws/daily_for_env_by_block/main.go @@ -35,15 +35,18 @@ func main() { Granularity: infra_sdk.CostGranularityDaily, FilterTags: []infra_sdk.CostFilterTag{ { - Key: infra_sdk.StandardTagStack, + Key: infra_sdk.UniversalTagStack, Values: stacks, }, { - Key: infra_sdk.StandardTagEnv, + Key: infra_sdk.UniversalTagEnv, Values: envs, }, }, - GroupTags: []infra_sdk.CostGroupTag{{Key: infra_sdk.StandardTagBlock}}, + GroupBy: infra_sdk.CostGroupIdentifiers{ + {Dimension: infra_sdk.UniversalDimensionAccount}, + {TagKey: infra_sdk.UniversalTagBlock}, + }, } result, err := coster.GetCosts(ctx, query) if err != nil { diff --git a/standard_tags.go b/standard_tags.go deleted file mode 100644 index 607b1e9..0000000 --- a/standard_tags.go +++ /dev/null @@ -1,33 +0,0 @@ -package infra_sdk - -const ( - StandardTagStack = "nullstone.io/stack" - StandardTagEnv = "nullstone.io/env" - StandardTagBlock = "nullstone.io/block" -) - -// MapStandardTagToLegacy maps the standard tag keys to ones that every Nullstone module contains -// Eventually, the Nullstone modules will use the standard tag keys instead -func MapStandardTagToLegacy(input string) string { - switch input { - case StandardTagStack: - return "Stack" - case StandardTagEnv: - return "Env" - case StandardTagBlock: - return "Block" - } - return input -} - -func MapLegacyTagToStandard(input string) string { - switch input { - case "Stack": - return StandardTagStack - case "Env": - return StandardTagEnv - case "Block": - return StandardTagBlock - } - return input -} diff --git a/universal_names.go b/universal_names.go new file mode 100644 index 0000000..69b0b99 --- /dev/null +++ b/universal_names.go @@ -0,0 +1,9 @@ +package infra_sdk + +const ( + UniversalTagStack = "nullstone.io/stack" + UniversalTagEnv = "nullstone.io/env" + UniversalTagBlock = "nullstone.io/block" + + UniversalDimensionAccount = "nullstone.io/cloud-account" +) From e15d1de5527c96785bbffc4b34a5dd03b403f7b1 Mon Sep 17 00:00:00 2001 From: Brad Sickles Date: Thu, 6 Nov 2025 12:23:39 -0500 Subject: [PATCH 5/9] Added MultiCoster which aggregates cost results from several providers --- builtin/coster_creator.go | 32 ------ builtin/discover_coster.go | 37 +++++++ coster.go | 28 +++++- go.mod | 4 + go.sum | 3 + multi_coster.go | 58 +++++++++++ multi_coster_test.go | 196 +++++++++++++++++++++++++++++++++++++ 7 files changed, 324 insertions(+), 34 deletions(-) delete mode 100644 builtin/coster_creator.go create mode 100644 builtin/discover_coster.go create mode 100644 multi_coster.go create mode 100644 multi_coster_test.go diff --git a/builtin/coster_creator.go b/builtin/coster_creator.go deleted file mode 100644 index a81a085..0000000 --- a/builtin/coster_creator.go +++ /dev/null @@ -1,32 +0,0 @@ -package builtin - -import ( - "context" - - infra_sdk "github.com/nullstone-io/infra-sdk" - "github.com/nullstone-io/infra-sdk/access/aws" - aws_account "github.com/nullstone-io/infra-sdk/builtin/aws/aws-account" - "gopkg.in/nullstone-io/go-api-client.v0/types" -) - -type CosterCreator struct { - AwsAssumer aws.Assumer -} - -func (s CosterCreator) NewCoster(ctx context.Context, getProviderFn GetProviderFunc, orgName string, providerConfig types.ProviderConfig) (infra_sdk.Coster, error) { - if providerConfig.Aws != nil && providerConfig.Aws.ProviderName != "" { - provider, err := getProviderFn(ctx, orgName, providerConfig.Aws.ProviderName) - if err != nil { - return nil, err - } else if provider != nil { - return aws_account.Coster{ - Assumer: s.AwsAssumer, - Provider: *provider, - }, nil - } - } - if providerConfig.Gcp != nil { - // TODO: Implement GCP - } - return nil, nil -} diff --git a/builtin/discover_coster.go b/builtin/discover_coster.go new file mode 100644 index 0000000..9182a48 --- /dev/null +++ b/builtin/discover_coster.go @@ -0,0 +1,37 @@ +package builtin + +import ( + infra_sdk "github.com/nullstone-io/infra-sdk" + "github.com/nullstone-io/infra-sdk/access/aws" + aws_account "github.com/nullstone-io/infra-sdk/builtin/aws/aws-account" + "gopkg.in/nullstone-io/go-api-client.v0/types" +) + +type CosterCreator struct { + AwsAssumer aws.Assumer +} + +func (s CosterCreator) NewMultiCoster(providers []types.Provider) (infra_sdk.MultiCoster, error) { + mc := infra_sdk.MultiCoster{Costers: []infra_sdk.Coster{}} + for _, cur := range providers { + coster, err := s.DiscoverCoster(cur) + if err != nil { + return mc, err + } + mc.Costers = append(mc.Costers, coster) + } + return mc, nil +} + +func (s CosterCreator) DiscoverCoster(provider types.Provider) (infra_sdk.Coster, error) { + switch provider.ProviderType { + case "aws": + return aws_account.Coster{ + Assumer: s.AwsAssumer, + Provider: provider, + }, nil + case "gcp": + // TODO: Implement GCP + } + return nil, nil +} diff --git a/coster.go b/coster.go index 36a6367..b46ccd7 100644 --- a/coster.go +++ b/coster.go @@ -3,6 +3,7 @@ package infra_sdk import ( "context" "fmt" + "slices" "strings" "time" ) @@ -79,6 +80,29 @@ func (r *CostResult) AddDatapoint(metricName string, groupKeys CostSeriesGroupKe r.Series[seriesKey] = cur } +// MergeDatapoint acts like AddDatapoint except it will not add a duplicate datapoint +// This is detected by comparing start+end times on the datapoint +func (r *CostResult) MergeDatapoint(metricName string, groupKeys CostSeriesGroupKeys, datapoint CostSeriesDatapoint) { + seriesKey := fmt.Sprintf("%s:%s", groupKeys.UniqueIdentifier(), metricName) + cur, ok := r.Series[seriesKey] + if !ok { + cur = CostSeries{ + MetricName: metricName, + GroupKeys: groupKeys, + Points: []CostSeriesDatapoint{}, + } + } + + isSameDatapoint := func(cur CostSeriesDatapoint) bool { + return cur.Start == datapoint.Start && cur.End == datapoint.End + } + if slices.ContainsFunc(cur.Points, isSameDatapoint) { + return + } + cur.Points = append(cur.Points, datapoint) + r.Series[seriesKey] = cur +} + func NewCostResult() *CostResult { return &CostResult{ Series: map[string]CostSeries{}, @@ -109,8 +133,8 @@ func (s CostSeriesGroupKeys) UniqueIdentifier() string { // If the group key is a tag, TagKey and TagValue are populated. // Otherwise, Name is populated. type CostSeriesGroupKey struct { - Name string `json:"name"` - TagKey string `json:"tagKey"` + Name string `json:"name,omitempty"` + TagKey string `json:"tagKey,omitempty"` Value string `json:"value"` } diff --git a/go.mod b/go.mod index 6ec2579..acf652d 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sns v1.39.1 github.com/aws/aws-sdk-go-v2/service/sqs v1.42.11 github.com/aws/aws-sdk-go-v2/service/sts v1.38.9 + github.com/stretchr/testify v1.11.1 golang.org/x/net v0.46.0 gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251028222640-d27c71d5cd3c ) @@ -41,12 +42,14 @@ require ( github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.11 // indirect github.com/aws/smithy-go v1.23.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/hcl/v2 v2.24.0 // indirect github.com/jinzhu/copier v0.4.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/nullstone-io/module v0.2.10 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/tmccombs/hcl2json v0.6.8 // indirect github.com/zclconf/go-cty v1.17.0 // indirect @@ -54,4 +57,5 @@ require ( golang.org/x/sync v0.17.0 // indirect golang.org/x/text v0.30.0 // indirect golang.org/x/tools v0.38.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index c65495e..4df8542 100644 --- a/go.sum +++ b/go.sum @@ -88,8 +88,10 @@ github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQx github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= @@ -148,6 +150,7 @@ golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251028222640-d27c71d5cd3c h1:0tx+r3tgGorPT6EWXawRiT3PFi5GBPMW1OIuc6kW+9U= gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251028222640-d27c71d5cd3c/go.mod h1:Bj01hknD135uWb7j+9EIcE775ZXYv9pWSXdryTHMrhM= diff --git a/multi_coster.go b/multi_coster.go new file mode 100644 index 0000000..01be0c9 --- /dev/null +++ b/multi_coster.go @@ -0,0 +1,58 @@ +package infra_sdk + +import ( + "context" + "errors" + "sync" +) + +// MultiCoster runs cost queries against multiple costers +// Results are combined into a single CostResult +type MultiCoster struct { + Costers []Coster +} + +type costerResult struct { + costResult *CostResult + err error +} + +func (c *MultiCoster) GetCosts(ctx context.Context, query CostQuery) (*CostResult, error) { + results := make(chan costerResult, len(c.Costers)) + var wg sync.WaitGroup + // Run each coster concurrently + for _, cur := range c.Costers { + wg.Add(1) + go func(coster Coster) { + defer wg.Done() + costResult, err := coster.GetCosts(ctx, query) + results <- costerResult{ + costResult: costResult, + err: err, + } + }(cur) + } + + // Wait for all costers to finish + go func() { + wg.Wait() + close(results) + }() + + // Combine results real-time + var errs []error + combinedResult := NewCostResult() + for res := range results { + if res.err != nil { + errs = append(errs, res.err) + continue + } + for _, series := range res.costResult.Series { + for _, point := range series.Points { + combinedResult.MergeDatapoint(series.MetricName, series.GroupKeys, point) + } + } + } + + return combinedResult, errors.Join(errs...) +} diff --git a/multi_coster_test.go b/multi_coster_test.go new file mode 100644 index 0000000..9310e1f --- /dev/null +++ b/multi_coster_test.go @@ -0,0 +1,196 @@ +package infra_sdk + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +type mockCoster struct { + result *CostResult + err error +} + +func (m *mockCoster) GetCosts(ctx context.Context, query CostQuery) (*CostResult, error) { + if m.err != nil { + return nil, m.err + } + return m.result, nil +} + +func TestMultiCoster_GetCosts(t *testing.T) { + now := time.Now().UTC() + dayAgo := now.Add(-24 * time.Hour) + tests := []struct { + name string + costers []Coster + expectError bool + validate func(t *testing.T, result *CostResult) + }{ + { + name: "no costers returns empty result", + costers: []Coster{}, + expectError: false, + validate: func(t *testing.T, result *CostResult) { + assert.Empty(t, result.Series) + }, + }, + { + name: "single coster returns its result", + costers: []Coster{ + &mockCoster{ + result: &CostResult{ + Series: map[string]CostSeries{ + "nullstone.io/cloud-account$123:cost": { + MetricName: "cost", + GroupKeys: CostSeriesGroupKeys{{Name: UniversalDimensionAccount, Value: "123"}}, + Points: []CostSeriesDatapoint{{ + Start: dayAgo, + End: now, + Value: "100.00", + Unit: "USD", + }}, + }, + }, + }, + }, + }, + expectError: false, + validate: func(t *testing.T, result *CostResult) { + require.Len(t, result.Series, 1) + series, exists := result.Series["nullstone.io/cloud-account$123:cost"] + require.True(t, exists) + assert.Equal(t, "cost", series.MetricName) + require.Len(t, series.Points, 1) + assert.Equal(t, "100.00", series.Points[0].Value) + }, + }, + { + name: "multiple costers with no overlaps are combined", + costers: []Coster{ + &mockCoster{ + result: &CostResult{ + Series: map[string]CostSeries{ + "nullstone-io/cloud-account$123": { + MetricName: "cost", + GroupKeys: CostSeriesGroupKeys{{Name: UniversalDimensionAccount, Value: "123"}}, + Points: []CostSeriesDatapoint{{ + Start: dayAgo, + End: now, + Value: "100.00", + Unit: "USD", + }}, + }, + }, + }, + }, + &mockCoster{ + result: &CostResult{ + Series: map[string]CostSeries{ + "nullstone-io/cloud-account$456": { + MetricName: "cost", + GroupKeys: CostSeriesGroupKeys{{Name: UniversalDimensionAccount, Value: "456"}}, + Points: []CostSeriesDatapoint{{ + Start: dayAgo, + End: now, + Value: "200.00", + Unit: "USD", + }}, + }, + }, + }, + }, + }, + expectError: false, + validate: func(t *testing.T, result *CostResult) { + require.Len(t, result.Series, 2) + + series1, exists := result.Series["nullstone.io/cloud-account$123:cost"] + require.True(t, exists) + assert.Equal(t, "cost", series1.MetricName) + require.Len(t, series1.Points, 1) + assert.Equal(t, "100.00", series1.Points[0].Value) + + series2, exists := result.Series["nullstone.io/cloud-account$456:cost"] + require.True(t, exists) + assert.Equal(t, "cost", series2.MetricName) + require.Len(t, series2.Points, 1) + assert.Equal(t, "200.00", series2.Points[0].Value) + }, + }, + { + name: "multiple costers with overlapping series are deduped", + costers: []Coster{ + &mockCoster{ + result: &CostResult{ + Series: map[string]CostSeries{ + "nullstone-io/cloud-account$123": { + MetricName: "cost", + GroupKeys: CostSeriesGroupKeys{{Name: UniversalDimensionAccount, Value: "123"}}, + Points: []CostSeriesDatapoint{{ + Start: dayAgo, + End: now, + Value: "100.00", + Unit: "USD", + }}, + }, + }, + }, + }, + &mockCoster{ + result: &CostResult{ + Series: map[string]CostSeries{ + "nullstone-io/cloud-account$123": { + MetricName: "cost", + GroupKeys: CostSeriesGroupKeys{{Name: UniversalDimensionAccount, Value: "123"}}, + Points: []CostSeriesDatapoint{{ + Start: dayAgo, + End: now, + Value: "200.00", + Unit: "USD", + }}, + }, + }, + }, + }, + }, + expectError: false, + validate: func(t *testing.T, result *CostResult) { + require.Len(t, result.Series, 1) + series, exists := result.Series["nullstone.io/cloud-account$123:cost"] + require.True(t, exists) + assert.Equal(t, "cost", series.MetricName) + // Should only have one point since the second one is a duplicate + require.Len(t, series.Points, 1) + }, + }, + { + name: "error from any coster is returned", + costers: []Coster{ + &mockCoster{ + err: assert.AnError, + }, + }, + expectError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mc := &MultiCoster{ + Costers: tt.costers, + } + + result, err := mc.GetCosts(context.Background(), CostQuery{}) + if tt.expectError { + assert.Error(t, err) + } else { + require.NoError(t, err) + tt.validate(t, result) + } + }) + } +} From 9b319055e581d6c06910bba864a776e7bc420e9a Mon Sep 17 00:00:00 2001 From: Brad Sickles Date: Thu, 6 Nov 2025 12:32:05 -0500 Subject: [PATCH 6/9] update go-api-client --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index acf652d..867b49c 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.38.9 github.com/stretchr/testify v1.11.1 golang.org/x/net v0.46.0 - gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251028222640-d27c71d5cd3c + gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251105201948-2bdfae663a5b ) require ( diff --git a/go.sum b/go.sum index 4df8542..e0ecac3 100644 --- a/go.sum +++ b/go.sum @@ -152,8 +152,8 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251028222640-d27c71d5cd3c h1:0tx+r3tgGorPT6EWXawRiT3PFi5GBPMW1OIuc6kW+9U= -gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251028222640-d27c71d5cd3c/go.mod h1:Bj01hknD135uWb7j+9EIcE775ZXYv9pWSXdryTHMrhM= +gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251105201948-2bdfae663a5b h1:AJq/KZ8LJ3BT7d+wV5z5UW7C9fQgJdBuM/aiE9LUUZM= +gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251105201948-2bdfae663a5b/go.mod h1:Bj01hknD135uWb7j+9EIcE775ZXYv9pWSXdryTHMrhM= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 4068bc974eaa62d01d5eeeff21cbaf9c5c3784ab Mon Sep 17 00:00:00 2001 From: Brad Sickles Date: Thu, 6 Nov 2025 15:01:57 -0500 Subject: [PATCH 7/9] drop log statement --- builtin/aws/aws-account/coster.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/builtin/aws/aws-account/coster.go b/builtin/aws/aws-account/coster.go index 8b7f7cf..707f08d 100644 --- a/builtin/aws/aws-account/coster.go +++ b/builtin/aws/aws-account/coster.go @@ -2,9 +2,7 @@ package aws_account import ( "context" - "encoding/json" "fmt" - "log" ce "github.com/aws/aws-sdk-go-v2/service/costexplorer" cetypes "github.com/aws/aws-sdk-go-v2/service/costexplorer/types" @@ -53,8 +51,6 @@ func (c Coster) GetCosts(ctx context.Context, query infra_sdk.CostQuery) (*infra Filter: costQueryToFilter(query), GroupBy: costQueryToGroupBy(groupBy), } - rawInput, _ := json.Marshal(input) - log.Println("input", string(rawInput)) aggregator := NewCostResultAggregator() var nextToken *string From 91822d4cfec51e0fd54758a3e85550facae0edf5 Mon Sep 17 00:00:00 2001 From: Brad Sickles Date: Mon, 10 Nov 2025 15:27:38 -0500 Subject: [PATCH 8/9] update go-api-client --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 867b49c..e6acfca 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.38.9 github.com/stretchr/testify v1.11.1 golang.org/x/net v0.46.0 - gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251105201948-2bdfae663a5b + gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251110195425-e7a9dedd8aba ) require ( diff --git a/go.sum b/go.sum index e0ecac3..7555008 100644 --- a/go.sum +++ b/go.sum @@ -152,8 +152,8 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251105201948-2bdfae663a5b h1:AJq/KZ8LJ3BT7d+wV5z5UW7C9fQgJdBuM/aiE9LUUZM= -gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251105201948-2bdfae663a5b/go.mod h1:Bj01hknD135uWb7j+9EIcE775ZXYv9pWSXdryTHMrhM= +gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251110195425-e7a9dedd8aba h1:6BIxKc6vSCyHq4gelY2TGZ6MMWSVhjc7DSwva+qGmt8= +gopkg.in/nullstone-io/go-api-client.v0 v0.0.0-20251110195425-e7a9dedd8aba/go.mod h1:Bj01hknD135uWb7j+9EIcE775ZXYv9pWSXdryTHMrhM= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 9268a0cccd117dbd2679b29109ffd4c5f135e0ec Mon Sep 17 00:00:00 2001 From: Brad Sickles Date: Mon, 10 Nov 2025 15:39:08 -0500 Subject: [PATCH 9/9] added tests --- .github/workflows/test.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..103cd98 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,37 @@ +name: Test infra-sdk + +on: + push: + branches: [ $default-branch ] + pull_request: {} + +jobs: + test: + runs-on: ubuntu-latest + permissions: + contents: read + issues: read + checks: write + pull-requests: write + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.25 + cache: true + - name: Set up gotestsum + run: go install gotest.tools/gotestsum@latest + - name: Run tests + run: | + mkdir -p build/test-results + gotestsum \ + --format=short-verbose \ + --junitfile build/test-results/go-junit.xml \ + ./... + - name: Publish test results + uses: EnricoMi/publish-unit-test-result-action@v2 + with: + files: build/test-results/**/*.xml + check_name: Go Tests