diff --git a/cmd/go.mod b/cmd/go.mod index ffaba24..4a53849 100644 --- a/cmd/go.mod +++ b/cmd/go.mod @@ -9,8 +9,8 @@ require ( github.com/posit-dev/ptd/lib v0.0.0-00010101000000-000000000000 github.com/spf13/cobra v1.9.1 github.com/spf13/viper v1.20.1 - github.com/stretchr/testify v1.10.0 - golang.org/x/term v0.37.0 + github.com/stretchr/testify v1.11.1 + golang.org/x/term v0.39.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -61,6 +61,8 @@ require ( github.com/aws/smithy-go v1.23.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/blang/semver v3.5.1+incompatible // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charmbracelet/bubbles v0.21.0 // indirect github.com/charmbracelet/bubbletea v1.3.6 // indirect github.com/charmbracelet/colorprofile v0.3.1 // indirect @@ -69,7 +71,7 @@ require ( github.com/charmbracelet/x/cellbuf v0.0.13 // indirect github.com/charmbracelet/x/term v0.2.1 // indirect github.com/cheggaaa/pb v1.0.29 // indirect - github.com/cloudflare/circl v1.6.1 // indirect + github.com/cloudflare/circl v1.6.3 // indirect github.com/coder/websocket v1.8.12 // indirect github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect @@ -81,9 +83,11 @@ require ( github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.6.2 // indirect - github.com/go-git/go-git/v5 v5.16.2 // indirect + github.com/go-git/go-git/v5 v5.16.5 // indirect github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.2 // indirect @@ -91,16 +95,20 @@ require ( github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 // indirect github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-version v1.8.0 // indirect github.com/hashicorp/hcl/v2 v2.24.0 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/iwdgo/sigintwindows v0.2.2 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jsimonetti/rtnetlink v1.4.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/klauspost/compress v1.18.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect @@ -111,6 +119,8 @@ require ( github.com/mdlayher/socket v0.5.0 // indirect github.com/mitchellh/go-ps v1.0.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/termenv v0.16.0 // indirect @@ -127,13 +137,15 @@ require ( github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231 // indirect github.com/pulumi/esc v0.17.0 // indirect github.com/pulumi/pulumi-azure-native-sdk/containerservice/v3 v3.6.1 // indirect - github.com/pulumi/pulumi-azure-native-sdk/v3 v3.8.0 // indirect - github.com/pulumi/pulumi/sdk/v3 v3.193.0 // indirect + github.com/pulumi/pulumi-azure-native-sdk/keyvault/v3 v3.14.0 // indirect + github.com/pulumi/pulumi-azure-native-sdk/v3 v3.14.0 // indirect + github.com/pulumi/pulumi-postgresql/sdk/v3 v3.16.2 // indirect + github.com/pulumi/pulumi-random/sdk/v4 v4.19.1 // indirect + github.com/pulumi/pulumi/sdk/v3 v3.224.0 // indirect github.com/redis/go-redis/v9 v9.10.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rstudio/rskey v0.6.0 // indirect - github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 // indirect github.com/sagikazarmark/locafero v0.9.0 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/sergi/go-diff v1.4.0 // indirect @@ -141,7 +153,7 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.9.2 // indirect - github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/pflag v1.0.10 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 // indirect github.com/texttheater/golang-levenshtein v1.0.1 // indirect @@ -151,26 +163,34 @@ require ( github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/zclconf/go-cty v1.16.3 // indirect - go.opentelemetry.io/otel/metric v1.37.0 // indirect - go.opentelemetry.io/otel/sdk v1.37.0 // indirect - go.opentelemetry.io/otel/trace v1.37.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/collector/featuregate v1.51.0 // indirect + go.opentelemetry.io/collector/pdata v1.51.0 // indirect + go.opentelemetry.io/otel v1.40.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 // indirect + go.opentelemetry.io/otel/metric v1.40.0 // indirect + go.opentelemetry.io/otel/sdk v1.40.0 // indirect + go.opentelemetry.io/otel/trace v1.40.0 // indirect + go.opentelemetry.io/proto/otlp v1.9.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.45.0 // indirect + golang.org/x/crypto v0.47.0 // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect - golang.org/x/mod v0.29.0 // indirect - golang.org/x/net v0.47.0 // indirect - golang.org/x/sync v0.18.0 // indirect - golang.org/x/sys v0.38.0 // indirect - golang.org/x/text v0.31.0 // indirect - golang.org/x/tools v0.38.0 // indirect + golang.org/x/mod v0.31.0 // indirect + golang.org/x/net v0.49.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/text v0.33.0 // indirect + golang.org/x/tools v0.40.0 // indirect golang.zx2c4.com/wireguard/windows v0.5.3 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect - google.golang.org/grpc v1.73.0 // indirect - google.golang.org/protobuf v1.36.6 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect + google.golang.org/grpc v1.78.0 // indirect + google.golang.org/protobuf v1.36.11 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/cmd/go.sum b/cmd/go.sum index 890e1e1..52bad9b 100644 --- a/cmd/go.sum +++ b/cmd/go.sum @@ -109,6 +109,8 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs= @@ -131,8 +133,8 @@ github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= -github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= -github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= +github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= +github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo= github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6 h1:8h5+bWd7R6AYUslN6c6iuZWTKsKxUFDlpnmilO6R2n0= @@ -178,12 +180,13 @@ github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UN github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM= -github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= +github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s= +github.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M= github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874 h1:F8d1AJ6M9UQCavhwmO6ZsrYLfG8zVFWfEfMS2MXPkSY= github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M= github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +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= @@ -209,10 +212,13 @@ github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= 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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806 h1:wG8RYIyctLhdFk6Vl1yPGtSRtwGpVkWyZww1OCil2MI= github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806/go.mod h1:Beg6V6zZ3oEn0JuiUQ4wqwuyqqzasOltcoXPtgLbFp4= 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/grpc-ecosystem/grpc-gateway/v2 v2.27.7 h1:X+2YciYSxvMQK0UZ7sg45ZVabVZBeBuvMkmuI2V3Fak= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7/go.mod h1:lW34nIZuQ8UDPdkon5fmfp2l3+ZkQ2me/+oecHYLOII= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -220,6 +226,8 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= +github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= @@ -234,6 +242,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jsimonetti/rtnetlink v1.4.0 h1:Z1BF0fRgcETPEa0Kt0MRk3yV5+kF1FWTni6KUFKrq2I= github.com/jsimonetti/rtnetlink v1.4.0/go.mod h1:5W1jDvWdnthFJ7fxYX1GMK07BUpI4oskfOqvPteYS6E= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= @@ -241,6 +251,8 @@ github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXw github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= 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= @@ -274,6 +286,12 @@ github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= 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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= @@ -312,10 +330,16 @@ github.com/pulumi/esc v0.17.0 h1:oaVOIyFTENlYDuqc3pW75lQT9jb2cd6ie/4/Twxn66w= github.com/pulumi/esc v0.17.0/go.mod h1:XnSxlt5NkmuAj304l/gK4pRErFbtqq6XpfX1tYT9Jbc= github.com/pulumi/pulumi-azure-native-sdk/containerservice/v3 v3.6.1 h1:+TOXp54h+42zk6/dHDYUEUgHph0oCIIHave+1PlNAek= github.com/pulumi/pulumi-azure-native-sdk/containerservice/v3 v3.6.1/go.mod h1:N7eNJSg9C7gJETX1PNx3c54XaB5LhxD8xIzQkv7QpfU= -github.com/pulumi/pulumi-azure-native-sdk/v3 v3.8.0 h1:bEeU+2UT3OuhiFvu/dlwy9MxigGp+nzcITuNbKQsGZY= -github.com/pulumi/pulumi-azure-native-sdk/v3 v3.8.0/go.mod h1:n4tbRXG0Q8I7WaE9Flx+yfN63x1fScZxa/ICHuwgED8= -github.com/pulumi/pulumi/sdk/v3 v3.193.0 h1:xGI3GfZ10hSwBqRPyz/E0kPeGuel5BplDQF3eGTu75o= -github.com/pulumi/pulumi/sdk/v3 v3.193.0/go.mod h1:aV0+c5xpSYccWKmOjTZS9liYCqh7+peu3cQgSXu7CJw= +github.com/pulumi/pulumi-azure-native-sdk/keyvault/v3 v3.14.0 h1:CA6jNQZUtf8qdhOLnYfOiHHCpJp7abJ05vJ70evkPGA= +github.com/pulumi/pulumi-azure-native-sdk/keyvault/v3 v3.14.0/go.mod h1:2SsOSG9eSukr+3ooK8j5aq3u2NNMCatYDPgVPrL9ucE= +github.com/pulumi/pulumi-azure-native-sdk/v3 v3.14.0 h1:29XtsDNMNqDOjWqTyHnN0KoQAMvboNPnVYSbnVH9mFY= +github.com/pulumi/pulumi-azure-native-sdk/v3 v3.14.0/go.mod h1:HpTlXFm+yGTmCdDj3rszMvzS0OBk1kpN2TNbAwnChNI= +github.com/pulumi/pulumi-postgresql/sdk/v3 v3.16.2 h1:ln9wupML+tgM3vtO5XtRHe5LemCqpzVTprB/wRcP+ig= +github.com/pulumi/pulumi-postgresql/sdk/v3 v3.16.2/go.mod h1:PQlILfLvIdkUPSv3ms2RfsflJEWG7/hqmUJrwt8Vpj8= +github.com/pulumi/pulumi-random/sdk/v4 v4.19.1 h1:MUr4+gUQy+wqhoHsuhXO6ypT40KhU9j/2DT05YU9KIg= +github.com/pulumi/pulumi-random/sdk/v4 v4.19.1/go.mod h1:AJpJvPU3qJaq02VUui3rMZHchvVpTvVuVp0lbCeEE50= +github.com/pulumi/pulumi/sdk/v3 v3.224.0 h1:z/4vxGI2oO9IY6Jr5pJ5rCCfaF0D9CDMyf71vTvLots= +github.com/pulumi/pulumi/sdk/v3 v3.224.0/go.mod h1:O6FsKAEKCj3axqPQ6DyMUn/07pN1I2vq9wI1WFEuxnI= github.com/redis/go-redis/v9 v9.10.0 h1:FxwK3eV8p/CQa0Ch276C7u2d0eNC9kCmAYQ7mCXCzVs= github.com/redis/go-redis/v9 v9.10.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -326,8 +350,6 @@ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7 github.com/rstudio/rskey v0.6.0 h1:k+jMnV9TvgQEg4C/vJQPuzCfMqfbrLoil61zGlikZ3Q= github.com/rstudio/rskey v0.6.0/go.mod h1:4R8tAN3pJVKWHUxty1X7lCpNStqV2t8imp/4wvyMiuI= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI= -github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs= github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k= github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= @@ -345,8 +367,9 @@ github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -356,9 +379,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -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/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 h1:Gzfnfk2TWrk8Jj4P4c1a3CtQyMaTVCznlkLZI++hok4= @@ -385,20 +407,40 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zclconf/go-cty v1.16.3 h1:osr++gw2T61A8KVYHoQiFbFd1Lh3JOCXc/jFLJXKTxk= github.com/zclconf/go-cty v1.16.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= -go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= -go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= -go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= -go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= -go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= -go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= -go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= -go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +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/collector/featuregate v1.51.0 h1:dxJuv/3T84dhNKp7fz5+8srHz1dhquGzDpLW4OZTFBw= +go.opentelemetry.io/collector/featuregate v1.51.0/go.mod h1:/1bclXgP91pISaEeNulRxzzmzMTm4I5Xih2SnI4HRSo= +go.opentelemetry.io/collector/internal/testutil v0.145.0 h1:H/KL0GH3kGqSMKxZvnQ0B0CulfO9xdTg4DZf28uV7fY= +go.opentelemetry.io/collector/internal/testutil v0.145.0/go.mod h1:YAD9EAkwh/l5asZNbEBEUCqEjoL1OKMjAMoPjPqH76c= +go.opentelemetry.io/collector/pdata v1.51.0 h1:DnDhSEuDXNdzGRB7f6oOfXpbDApwBX3tY+3K69oUrDA= +go.opentelemetry.io/collector/pdata v1.51.0/go.mod h1:GoX1bjKDR++mgFKdT7Hynv9+mdgQ1DDXbjs7/Ww209Q= +go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= +go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0/go.mod h1:bTdK1nhqF76qiPoCCdyFIV+N/sRHYXYCTQc+3VCi3MI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 h1:DvJDOPmSWQHWywQS6lKL+pb8s3gBLOZUtw4N+mavW1I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0/go.mod h1:EtekO9DEJb4/jRyN4v4Qjc2yA7AtfCBuz2FynRUWTXs= +go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g= +go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc= +go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8= +go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE= +go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw= +go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg= +go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw= +go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= +go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= +go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= +go.opentelemetry.io/proto/slim/otlp v1.9.0 h1:fPVMv8tP3TrsqlkH1HWYUpbCY9cAIemx184VGkS6vlE= +go.opentelemetry.io/proto/slim/otlp v1.9.0/go.mod h1:xXdeJJ90Gqyll+orzUkY4bOd2HECo5JofeoLpymVqdI= +go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.2.0 h1:o13nadWDNkH/quoDomDUClnQBpdQQ2Qqv0lQBjIXjE8= +go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.2.0/go.mod h1:Gyb6Xe7FTi/6xBHwMmngGoHqL0w29Y4eW8TGFzpefGA= +go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.2.0 h1:EiUYvtwu6PMrMHVjcPfnsG3v+ajPkbUeH+IL93+QYyk= +go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.2.0/go.mod h1:mUUHKFiN2SST3AhJ8XhJxEoeVW12oqfXog0Bo8W3Ec4= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= @@ -411,29 +453,29 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= -golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -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/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= +golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= -golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -451,16 +493,16 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= -golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= +golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= +golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -469,8 +511,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= -golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= +golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= +golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -479,12 +521,16 @@ golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeu golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE= golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= -google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M= +google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= +google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= @@ -496,7 +542,6 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gvisor.dev/gvisor v0.0.0-20250205023644-9414b50a5633 h1:2gap+Kh/3F47cO6hAu3idFvsJ0ue6TRcEi2IUkv/F8k= diff --git a/docs/cli/ensure-flow.md b/docs/cli/ensure-flow.md index e920cc2..9544242 100644 --- a/docs/cli/ensure-flow.md +++ b/docs/cli/ensure-flow.md @@ -63,7 +63,7 @@ Provisions long-lived infrastructure components that persist across deployments. **Proxy Required**: Yes (connects to database) -**Implementation**: Python Pulumi (`python-pulumi/src/ptd/pulumi_resources/aws_control_room_postgres_config.py`) +**Implementation**: Inline Go Pulumi (`lib/steps/postgres_config.go`) Connects to the RDS PostgreSQL instance to configure: - Database users and permissions @@ -155,7 +155,7 @@ Creates the foundational infrastructure for the workload: **Proxy Required**: Yes (connects to database) -**Implementation**: Python Pulumi (`python-pulumi/src/ptd/pulumi_resources/aws_workload_postgres_config.py`) +**Implementation**: Inline Go Pulumi (`lib/steps/postgres_config.go`) Configures the RDS database created in the persistent step: - Creates databases for each Posit Team product diff --git a/lib/azure/secretstore.go b/lib/azure/secretstore.go index fea1ef4..2d2254b 100644 --- a/lib/azure/secretstore.go +++ b/lib/azure/secretstore.go @@ -26,7 +26,7 @@ func (s *SecretStore) GetSecretValue(ctx context.Context, credentials types.Cred if err != nil { return "", err } - return getSecretValue(ctx, azureCreds, s.region, secretName) + return getSecretValue(ctx, azureCreds, s.vaultName, secretName) } func (s *SecretStore) PutSecretValue(ctx context.Context, credentials types.Credentials, secretName string, secretString string) error { diff --git a/lib/go.mod b/lib/go.mod index ab7f029..f54d594 100644 --- a/lib/go.mod +++ b/lib/go.mod @@ -23,11 +23,14 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 github.com/containers/image/v5 v5.35.0 github.com/google/uuid v1.6.0 - github.com/pulumi/pulumi/sdk/v3 v3.193.0 + github.com/pulumi/pulumi-azure-native-sdk/keyvault/v3 v3.14.0 + github.com/pulumi/pulumi-postgresql/sdk/v3 v3.16.2 + github.com/pulumi/pulumi-random/sdk/v4 v4.19.1 + github.com/pulumi/pulumi/sdk/v3 v3.224.0 github.com/rstudio/rskey v0.6.0 github.com/spf13/viper v1.20.1 - github.com/stretchr/testify v1.10.0 - golang.org/x/text v0.31.0 + github.com/stretchr/testify v1.11.1 + golang.org/x/text v0.33.0 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 sigs.k8s.io/yaml v1.5.0 @@ -35,9 +38,23 @@ require ( ) require ( + github.com/cenkalti/backoff/v5 v5.0.3 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cilium/ebpf v0.16.0 // indirect - github.com/pulumi/pulumi-azure-native-sdk/v3 v3.8.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 // indirect + github.com/hashicorp/go-version v1.8.0 // indirect + github.com/pulumi/pulumi-azure-native-sdk/v3 v3.14.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/collector/featuregate v1.51.0 // indirect + go.opentelemetry.io/collector/pdata v1.51.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 // indirect + go.opentelemetry.io/otel/metric v1.40.0 // indirect + go.opentelemetry.io/otel/sdk v1.40.0 // indirect + go.opentelemetry.io/otel/trace v1.40.0 // indirect + go.opentelemetry.io/proto/otlp v1.9.0 // indirect pgregory.net/rapid v0.6.1 // indirect ) @@ -47,7 +64,6 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect - github.com/BurntSushi/toml v1.5.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/ProtonMail/go-crypto v1.3.0 // indirect github.com/VividCortex/ewma v1.2.0 // indirect @@ -81,7 +97,7 @@ require ( github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect github.com/charmbracelet/x/term v0.2.1 // indirect github.com/cheggaaa/pb v1.0.29 // indirect - github.com/cloudflare/circl v1.6.1 // indirect + github.com/cloudflare/circl v1.6.3 // indirect github.com/coder/websocket v1.8.12 // indirect github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect github.com/containers/ocicrypt v1.2.1 // indirect @@ -99,8 +115,8 @@ require ( github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.6.2 // indirect - github.com/go-git/go-git/v5 v5.16.2 // indirect - github.com/go-jose/go-jose/v4 v4.1.2 // indirect + github.com/go-git/go-git/v5 v5.16.5 // indirect + github.com/go-jose/go-jose/v4 v4.1.3 // indirect github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874 // indirect github.com/go-openapi/analysis v0.23.0 // indirect github.com/go-openapi/errors v0.22.1 // indirect @@ -152,7 +168,7 @@ require ( github.com/moby/sys/mountinfo v0.7.2 // indirect github.com/moby/sys/user v0.4.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/termenv v0.16.0 // indirect @@ -176,7 +192,6 @@ require ( github.com/pulumi/pulumi-azure-native-sdk/containerservice/v3 v3.6.1 github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect - github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 // indirect github.com/sagikazarmark/locafero v0.9.0 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/secure-systems-lab/go-securesystemslib v0.9.0 // indirect @@ -192,7 +207,7 @@ require ( github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.9.2 // indirect github.com/spf13/cobra v1.9.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/pflag v1.0.10 // indirect github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect @@ -209,25 +224,25 @@ require ( github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/zclconf/go-cty v1.16.3 // indirect go.mongodb.org/mongo-driver v1.17.4 // indirect - go.opentelemetry.io/otel v1.37.0 // indirect + go.opentelemetry.io/otel v1.40.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.yaml.in/yaml/v3 v3.0.3 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.45.0 // indirect + golang.org/x/crypto v0.47.0 // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect - golang.org/x/mod v0.29.0 // indirect - golang.org/x/net v0.47.0 // indirect - golang.org/x/sync v0.18.0 // indirect - golang.org/x/sys v0.38.0 // indirect - golang.org/x/term v0.37.0 // indirect - golang.org/x/tools v0.38.0 // indirect + golang.org/x/mod v0.31.0 // indirect + golang.org/x/net v0.49.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/term v0.39.0 // indirect + golang.org/x/tools v0.40.0 // indirect golang.zx2c4.com/wireguard/windows v0.5.3 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect - google.golang.org/grpc v1.73.0 // indirect - google.golang.org/protobuf v1.36.6 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect + google.golang.org/grpc v1.78.0 // indirect + google.golang.org/protobuf v1.36.11 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect lukechampine.com/frand v1.5.1 // indirect diff --git a/lib/go.sum b/lib/go.sum index 9f28e72..7793910 100644 --- a/lib/go.sum +++ b/lib/go.sum @@ -117,6 +117,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs= @@ -137,8 +139,8 @@ github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= -github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= -github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= +github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= +github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo= github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= github.com/containers/image/v5 v5.35.0 h1:T1OeyWp3GjObt47bchwD9cqiaAm/u4O4R9hIWdrdrP8= @@ -206,12 +208,13 @@ github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UN github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM= -github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= -github.com/go-jose/go-jose/v4 v4.1.2 h1:TK/7NqRQZfgAh+Td8AlsrvtPoUyiHh0LqVvokh+1vHI= -github.com/go-jose/go-jose/v4 v4.1.2/go.mod h1:22cg9HWM1pOlnRiY+9cQYJ9XHmya1bYW8OeDM6Ku6Oo= +github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s= +github.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M= +github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= +github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874 h1:F8d1AJ6M9UQCavhwmO6ZsrYLfG8zVFWfEfMS2MXPkSY= github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M= +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= @@ -269,6 +272,8 @@ 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/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 h1:X+2YciYSxvMQK0UZ7sg45ZVabVZBeBuvMkmuI2V3Fak= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7/go.mod h1:lW34nIZuQ8UDPdkon5fmfp2l3+ZkQ2me/+oecHYLOII= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -276,6 +281,8 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= +github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= @@ -359,8 +366,9 @@ github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= @@ -419,10 +427,16 @@ github.com/pulumi/esc v0.17.0 h1:oaVOIyFTENlYDuqc3pW75lQT9jb2cd6ie/4/Twxn66w= github.com/pulumi/esc v0.17.0/go.mod h1:XnSxlt5NkmuAj304l/gK4pRErFbtqq6XpfX1tYT9Jbc= github.com/pulumi/pulumi-azure-native-sdk/containerservice/v3 v3.6.1 h1:+TOXp54h+42zk6/dHDYUEUgHph0oCIIHave+1PlNAek= github.com/pulumi/pulumi-azure-native-sdk/containerservice/v3 v3.6.1/go.mod h1:N7eNJSg9C7gJETX1PNx3c54XaB5LhxD8xIzQkv7QpfU= -github.com/pulumi/pulumi-azure-native-sdk/v3 v3.8.0 h1:bEeU+2UT3OuhiFvu/dlwy9MxigGp+nzcITuNbKQsGZY= -github.com/pulumi/pulumi-azure-native-sdk/v3 v3.8.0/go.mod h1:n4tbRXG0Q8I7WaE9Flx+yfN63x1fScZxa/ICHuwgED8= -github.com/pulumi/pulumi/sdk/v3 v3.193.0 h1:xGI3GfZ10hSwBqRPyz/E0kPeGuel5BplDQF3eGTu75o= -github.com/pulumi/pulumi/sdk/v3 v3.193.0/go.mod h1:aV0+c5xpSYccWKmOjTZS9liYCqh7+peu3cQgSXu7CJw= +github.com/pulumi/pulumi-azure-native-sdk/keyvault/v3 v3.14.0 h1:CA6jNQZUtf8qdhOLnYfOiHHCpJp7abJ05vJ70evkPGA= +github.com/pulumi/pulumi-azure-native-sdk/keyvault/v3 v3.14.0/go.mod h1:2SsOSG9eSukr+3ooK8j5aq3u2NNMCatYDPgVPrL9ucE= +github.com/pulumi/pulumi-azure-native-sdk/v3 v3.14.0 h1:29XtsDNMNqDOjWqTyHnN0KoQAMvboNPnVYSbnVH9mFY= +github.com/pulumi/pulumi-azure-native-sdk/v3 v3.14.0/go.mod h1:HpTlXFm+yGTmCdDj3rszMvzS0OBk1kpN2TNbAwnChNI= +github.com/pulumi/pulumi-postgresql/sdk/v3 v3.16.2 h1:ln9wupML+tgM3vtO5XtRHe5LemCqpzVTprB/wRcP+ig= +github.com/pulumi/pulumi-postgresql/sdk/v3 v3.16.2/go.mod h1:PQlILfLvIdkUPSv3ms2RfsflJEWG7/hqmUJrwt8Vpj8= +github.com/pulumi/pulumi-random/sdk/v4 v4.19.1 h1:MUr4+gUQy+wqhoHsuhXO6ypT40KhU9j/2DT05YU9KIg= +github.com/pulumi/pulumi-random/sdk/v4 v4.19.1/go.mod h1:AJpJvPU3qJaq02VUui3rMZHchvVpTvVuVp0lbCeEE50= +github.com/pulumi/pulumi/sdk/v3 v3.224.0 h1:z/4vxGI2oO9IY6Jr5pJ5rCCfaF0D9CDMyf71vTvLots= +github.com/pulumi/pulumi/sdk/v3 v3.224.0/go.mod h1:O6FsKAEKCj3axqPQ6DyMUn/07pN1I2vq9wI1WFEuxnI= github.com/redis/go-redis/v9 v9.10.0 h1:FxwK3eV8p/CQa0Ch276C7u2d0eNC9kCmAYQ7mCXCzVs= github.com/redis/go-redis/v9 v9.10.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -433,8 +447,6 @@ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7 github.com/rstudio/rskey v0.6.0 h1:k+jMnV9TvgQEg4C/vJQPuzCfMqfbrLoil61zGlikZ3Q= github.com/rstudio/rskey v0.6.0/go.mod h1:4R8tAN3pJVKWHUxty1X7lCpNStqV2t8imp/4wvyMiuI= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI= -github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs= github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k= github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= @@ -468,8 +480,9 @@ github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 h1:pnnLyeX7o/5aX8qUQ69P/mLojDqwda8hFOCBTmP/6hw= @@ -481,10 +494,9 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -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/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 h1:Gzfnfk2TWrk8Jj4P4c1a3CtQyMaTVCznlkLZI++hok4= @@ -522,24 +534,44 @@ github.com/zclconf/go-cty v1.16.3 h1:osr++gw2T61A8KVYHoQiFbFd1Lh3JOCXc/jFLJXKTxk github.com/zclconf/go-cty v1.16.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw= go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= -go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= -go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= -go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= -go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= -go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= -go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= -go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= -go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +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/collector/featuregate v1.51.0 h1:dxJuv/3T84dhNKp7fz5+8srHz1dhquGzDpLW4OZTFBw= +go.opentelemetry.io/collector/featuregate v1.51.0/go.mod h1:/1bclXgP91pISaEeNulRxzzmzMTm4I5Xih2SnI4HRSo= +go.opentelemetry.io/collector/internal/testutil v0.145.0 h1:H/KL0GH3kGqSMKxZvnQ0B0CulfO9xdTg4DZf28uV7fY= +go.opentelemetry.io/collector/internal/testutil v0.145.0/go.mod h1:YAD9EAkwh/l5asZNbEBEUCqEjoL1OKMjAMoPjPqH76c= +go.opentelemetry.io/collector/pdata v1.51.0 h1:DnDhSEuDXNdzGRB7f6oOfXpbDApwBX3tY+3K69oUrDA= +go.opentelemetry.io/collector/pdata v1.51.0/go.mod h1:GoX1bjKDR++mgFKdT7Hynv9+mdgQ1DDXbjs7/Ww209Q= +go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= +go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0/go.mod h1:bTdK1nhqF76qiPoCCdyFIV+N/sRHYXYCTQc+3VCi3MI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 h1:DvJDOPmSWQHWywQS6lKL+pb8s3gBLOZUtw4N+mavW1I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0/go.mod h1:EtekO9DEJb4/jRyN4v4Qjc2yA7AtfCBuz2FynRUWTXs= +go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g= +go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc= +go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8= +go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE= +go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw= +go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg= +go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw= +go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= +go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= +go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= +go.opentelemetry.io/proto/slim/otlp v1.9.0 h1:fPVMv8tP3TrsqlkH1HWYUpbCY9cAIemx184VGkS6vlE= +go.opentelemetry.io/proto/slim/otlp v1.9.0/go.mod h1:xXdeJJ90Gqyll+orzUkY4bOd2HECo5JofeoLpymVqdI= +go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.2.0 h1:o13nadWDNkH/quoDomDUClnQBpdQQ2Qqv0lQBjIXjE8= +go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.2.0/go.mod h1:Gyb6Xe7FTi/6xBHwMmngGoHqL0w29Y4eW8TGFzpefGA= +go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.2.0 h1:EiUYvtwu6PMrMHVjcPfnsG3v+ajPkbUeH+IL93+QYyk= +go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.2.0/go.mod h1:mUUHKFiN2SST3AhJ8XhJxEoeVW12oqfXog0Bo8W3Ec4= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= -go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= go4.org/mem v0.0.0-20240501181205-ae6ca9944745 h1:Tl++JLUCe4sxGu8cTpDzRLd3tN7US4hOxG5YpKCzkek= go4.org/mem v0.0.0-20240501181205-ae6ca9944745/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= @@ -553,8 +585,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= -golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= -golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= @@ -566,8 +598,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -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/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= +golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -581,8 +613,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -592,8 +624,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= -golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -619,8 +651,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -630,8 +662,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= -golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= -golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= +golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= +golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -642,8 +674,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -656,8 +688,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= -golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= +golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= +golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -666,14 +698,16 @@ golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeu golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE= golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI= -google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= -google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= -google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M= +google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= +google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/lib/pulumi/inline.go b/lib/pulumi/inline.go index cf003d1..5537e0d 100644 --- a/lib/pulumi/inline.go +++ b/lib/pulumi/inline.go @@ -14,6 +14,8 @@ import ( // Plugins required for the Pulumi stack. These should possibly be moved to a // manifest, but this is fine for now IMO. var RequiredPlugins = map[string]string{ + "random": "4.19.1", + "postgresql": "3.16.2", "aws": "6.65.0", "azure-native": "3.8.0", } diff --git a/lib/pulumi/python.go b/lib/pulumi/python.go index 26175ca..af1f98b 100644 --- a/lib/pulumi/python.go +++ b/lib/pulumi/python.go @@ -84,11 +84,7 @@ func NewPythonPulumiStack( // this is some ridiculous shit right here. // we're building the module and class name to continue supporting the ptd/pulumi-python autoload() feature // without needing to check the files into source code. - // the unicode word split algo also doesn't like "postgres_config", so just hack that in manually titleCaseStackBaseName := helpers.TitleCase(stackBaseName) - if stackBaseName == "postgres_config" { - titleCaseStackBaseName = "PostgresConfig" - } if stackBaseName == "eks" { titleCaseStackBaseName = "EKS" } diff --git a/lib/steps/aks.go b/lib/steps/aks.go index 16c834b..443a0ec 100644 --- a/lib/steps/aks.go +++ b/lib/steps/aks.go @@ -410,8 +410,8 @@ func getPersistentStackOutputs(ctx context.Context, target types.Target) (auto.O } persistentStack, err := ptdpulumi.NewPythonPulumiStack( ctx, - "azure", - "workload", + string(target.CloudProvider()), + string(target.Type()), "persistent", target.Name(), target.Region(), diff --git a/lib/steps/postgres_config.go b/lib/steps/postgres_config.go index 0adc8b1..a5b58c8 100644 --- a/lib/steps/postgres_config.go +++ b/lib/steps/postgres_config.go @@ -2,8 +2,18 @@ package steps import ( "context" + "encoding/json" + "errors" + "fmt" + "strings" - "github.com/posit-dev/ptd/lib/pulumi" + "github.com/pulumi/pulumi-azure-native-sdk/keyvault/v3" + "github.com/pulumi/pulumi-postgresql/sdk/v3/go/postgresql" + "github.com/pulumi/pulumi-random/sdk/v4/go/random" + "github.com/pulumi/pulumi/sdk/v3/go/pulumi" + + "github.com/posit-dev/ptd/lib/azure" + "github.com/posit-dev/ptd/lib/helpers" "github.com/posit-dev/ptd/lib/types" ) @@ -28,12 +38,10 @@ func (s *PostgresConfigStep) Set(t types.Target, controlRoomTarget types.Target, } func (s *PostgresConfigStep) Run(ctx context.Context) error { - targetType := "workload" - if s.DstTarget.ControlRoom() { - targetType = "control-room" + if s.DstTarget == nil { + return errors.New("postgres_config step requires a destination target") } - // get the credentials for the target creds, err := s.DstTarget.Credentials(ctx) if err != nil { return err @@ -48,26 +56,419 @@ func (s *PostgresConfigStep) Run(ctx context.Context) error { envVars["ALL_PROXY"] = "socks5://localhost:1080" // TODO: make this configurable } - stack, err := pulumi.NewPythonPulumiStack( - ctx, - string(s.DstTarget.CloudProvider()), // ptd--- - targetType, - "postgres_config", - s.DstTarget.Name(), - s.DstTarget.Region(), - s.DstTarget.PulumiBackendUrl(), - s.DstTarget.PulumiSecretsProviderKey(), - envVars, - true, - ) + switch s.DstTarget.CloudProvider() { + case types.AWS: + return s.runAWSInlineGo(ctx, creds, envVars) + case types.Azure: + return s.runAzureInlineGo(ctx, creds, envVars) + default: + return fmt.Errorf("unsupported cloud provider for postgres_config: %s", s.DstTarget.CloudProvider()) + } +} + +// --- AWS --- + +func (s *PostgresConfigStep) runAWSInlineGo(ctx context.Context, creds types.Credentials, envVars map[string]string) error { + // Fetch persistent stack outputs (db_address, db_secret_arn) + persistentOutputs, err := getPersistentStackOutputs(ctx, s.DstTarget) + if err != nil { + return fmt.Errorf("failed to get persistent stack outputs: %w", err) + } + + dbAddressOutput, ok := persistentOutputs["db_address"] + if !ok { + return fmt.Errorf("db_address output not found in persistent stack outputs") + } + dbAddress := dbAddressOutput.Value.(string) + + dbSecretArnOutput, ok := persistentOutputs["db_secret_arn"] + if !ok { + return fmt.Errorf("db_secret_arn output not found in persistent stack outputs") + } + dbSecretArn := dbSecretArnOutput.Value.(string) + + // Fetch RDS master password from AWS Secrets Manager + secretValue, err := s.DstTarget.SecretStore().GetSecretValue(ctx, creds, dbSecretArn) + if err != nil { + return fmt.Errorf("failed to get RDS master password: %w", err) + } + masterPassword, err := parseDBSecretField(secretValue, "password") if err != nil { return err } - err = pulumiRefreshPreviewUpCancel(ctx, stack, s.Options) + // Determine extra postgres DBs (workload only) + var extraPostgresDbs []string + if !s.DstTarget.ControlRoom() { + c, err := helpers.ConfigForTarget(s.DstTarget) + if err != nil { + return fmt.Errorf("failed to load config: %w", err) + } + if config, ok := c.(types.AWSWorkloadConfig); ok { + extraPostgresDbs = config.ExtraPostgresDbs + } + } + + stack, err := createStack(ctx, s.Name(), s.DstTarget, func(pctx *pulumi.Context, target types.Target) error { + return awsPostgresConfigDeploy(pctx, target, dbAddress, masterPassword, extraPostgresDbs) + }, envVars) if err != nil { return err } + return runPulumi(ctx, stack, s.Options) +} + +// --- Azure --- + +// azurePostgresParams holds the pre-fetched data needed by the Azure deploy function. +type azurePostgresParams struct { + dbHost string + dbUser string + dbPassword string + clusters []string // release names + vaultName string + resourceGroupName string + protectPersistentResources bool +} + +func (s *PostgresConfigStep) runAzureInlineGo(ctx context.Context, creds types.Credentials, envVars map[string]string) error { + azTarget, ok := s.DstTarget.(azure.Target) + if !ok { + return errors.New("expected Azure target for postgres_config step") + } + + vaultName := azTarget.VaultName() + resourceGroupName := azTarget.ResourceGroupName() + + // Fetch DB admin secret from Azure Key Vault + secretName := fmt.Sprintf("%s-grafana-postgres-admin-secret", s.DstTarget.Name()) + secretValue, err := s.DstTarget.SecretStore().GetSecretValue(ctx, creds, secretName) + if err != nil { + return fmt.Errorf("failed to get postgres admin secret from Key Vault: %w", err) + } + + var secretData map[string]string + if err := json.Unmarshal([]byte(secretValue), &secretData); err != nil { + return fmt.Errorf("failed to parse postgres admin secret JSON: %w", err) + } + + dbHost := secretData["fqdn"] + dbUser := secretData["username"] + dbPassword := secretData["password"] + if dbHost == "" || dbUser == "" || dbPassword == "" { + return fmt.Errorf("grafana DB secret must contain 'fqdn', 'username' and 'password' fields") + } + + // Load config to get cluster releases and protect flag + c, err := helpers.ConfigForTarget(s.DstTarget) + if err != nil { + return fmt.Errorf("failed to load config: %w", err) + } + config, ok := c.(types.AzureWorkloadConfig) + if !ok { + return errors.New("expected AzureWorkloadConfig for Azure postgres_config step") + } + + var releases []string + for release := range config.Clusters { + releases = append(releases, release) + } + + params := azurePostgresParams{ + dbHost: dbHost, + dbUser: dbUser, + dbPassword: dbPassword, + clusters: releases, + vaultName: vaultName, + resourceGroupName: resourceGroupName, + protectPersistentResources: config.ProtectPersistentResources, + } + + stack, err := createStack(ctx, s.Name(), s.DstTarget, func(pctx *pulumi.Context, target types.Target) error { + return azurePostgresConfigDeploy(pctx, target, params) + }, envVars) + if err != nil { + return err + } + + return runPulumi(ctx, stack, s.Options) +} + +// --- Shared helpers --- + +// parseDBSecretField extracts a field from a JSON secret string. +func parseDBSecretField(secretString string, field string) (string, error) { + var secretData map[string]string + if err := json.Unmarshal([]byte(secretString), &secretData); err != nil { + return "", fmt.Errorf("failed to parse DB secret JSON: %w", err) + } + return secretData[field], nil +} + +// --- AWS deploy --- + +// awsPostgresConfigDeploy creates PostgreSQL databases and roles for Grafana via inline Go Pulumi. +// It handles both control room and workload variants for AWS. +func awsPostgresConfigDeploy(ctx *pulumi.Context, target types.Target, dbAddress string, masterPassword string, extraPostgresDbs []string) error { + name := target.Name() + isControlRoom := target.ControlRoom() + + // Python component type for alias resolution + componentType := "ptd:AWSWorkloadPostgresConfig" + if isControlRoom { + componentType = "ptd:AWSControlRoomPostgresConfig" + } + + // Helper to create alias pointing to old Python component parent URN. + // Python resources were children of a ComponentResource, so their URNs included + // the component type as a parent prefix. Go inline resources are children of the + // Stack, so we need aliases for Pulumi to recognize them as the same resources. + withAlias := func() pulumi.ResourceOption { + parentURN := fmt.Sprintf("urn:pulumi:%s::%s::%s::%s", ctx.Stack(), ctx.Project(), componentType, name) + return pulumi.Aliases([]pulumi.Alias{{ParentURN: pulumi.URN(parentURN)}}) + } + + // Grafana role/db naming differs between control room and workload + grafanaRoleName := "grafana" + grafanaDBName := "grafana" + if !isControlRoom { + grafanaRoleName = fmt.Sprintf("grafana-%s", name) + grafanaDBName = fmt.Sprintf("grafana-%s", name) + } + + // 1. Random password for Grafana DB user + grafanaPw, err := random.NewRandomPassword(ctx, fmt.Sprintf("%s-db-grafana-pw", name), &random.RandomPasswordArgs{ + Special: pulumi.Bool(true), + OverrideSpecial: pulumi.String("-_"), + Length: pulumi.Int(36), + }, withAlias()) + if err != nil { + return fmt.Errorf("failed to create grafana password: %w", err) + } + + // 2. PostgreSQL provider pointing to RDS + pgProvider, err := postgresql.NewProvider(ctx, fmt.Sprintf("%s-postgres-provider", name), &postgresql.ProviderArgs{ + Host: pulumi.String(dbAddress), + Port: pulumi.Int(5432), + Sslmode: pulumi.String("require"), + Username: pulumi.String("postgres"), + Password: pulumi.String(masterPassword), + Superuser: pulumi.Bool(false), + }, withAlias()) + if err != nil { + return fmt.Errorf("failed to create postgres provider: %w", err) + } + + // 3. Grafana role + grafanaRole, err := postgresql.NewRole(ctx, fmt.Sprintf("%s-grafana-role", name), &postgresql.RoleArgs{ + Login: pulumi.Bool(true), + Name: pulumi.String(grafanaRoleName), + Password: grafanaPw.Result, + }, pulumi.Provider(pgProvider), withAlias()) + if err != nil { + return fmt.Errorf("failed to create grafana role: %w", err) + } + + // 4. Grafana database + grafanaDbOpts := []pulumi.ResourceOption{ + pulumi.Provider(pgProvider), + pulumi.DependsOn([]pulumi.Resource{grafanaRole}), + withAlias(), + } + if !isControlRoom { + grafanaDbOpts = append(grafanaDbOpts, pulumi.Protect(true)) + } + grafanaDb, err := postgresql.NewDatabase(ctx, fmt.Sprintf("%s-grafana-db", name), &postgresql.DatabaseArgs{ + Name: pulumi.String(grafanaDBName), + Owner: pulumi.String(grafanaRoleName), + }, grafanaDbOpts...) + if err != nil { + return fmt.Errorf("failed to create grafana database: %w", err) + } + + // 5. Grafana grant (CREATE, USAGE on public schema) + grant, err := postgresql.NewGrant(ctx, fmt.Sprintf("%s-grafana-grant", name), &postgresql.GrantArgs{ + Database: pulumi.String(grafanaDBName), + Role: pulumi.String(grafanaRoleName), + Schema: pulumi.String("public"), + ObjectType: pulumi.String("schema"), + Privileges: pulumi.StringArray{pulumi.String("CREATE"), pulumi.String("USAGE")}, + }, pulumi.Provider(pgProvider), pulumi.DependsOn([]pulumi.Resource{grafanaDb, grafanaRole}), withAlias()) + if err != nil { + return fmt.Errorf("failed to create grafana grant: %w", err) + } + + // Exports + if isControlRoom { + ctx.Export("db_grafana_connection", pulumi.Sprintf("postgres://grafana:%s@%s/grafana", grafanaPw.Result, pulumi.String(dbAddress))) + } + ctx.Export("db_grafana_pw", grafanaPw.Result) + ctx.Export("grafana_db_name", grafanaDb.Name) + ctx.Export("grant_id", grant.ID()) + + // Extra databases (workload only, e.g. soleng for staging workloads) + for _, dbn := range extraPostgresDbs { + dbName := strings.ReplaceAll(dbn, "-", "_") + + extraPw, err := random.NewRandomPassword(ctx, fmt.Sprintf("%s-db-%s-pw", name, dbName), &random.RandomPasswordArgs{ + Special: pulumi.Bool(true), + OverrideSpecial: pulumi.String("-_"), + Length: pulumi.Int(36), + }, withAlias()) + if err != nil { + return fmt.Errorf("failed to create %s password: %w", dbName, err) + } + + extraRole, err := postgresql.NewRole(ctx, fmt.Sprintf("%s-%s-role", name, dbName), &postgresql.RoleArgs{ + Login: pulumi.Bool(true), + Name: pulumi.String(dbName), + Password: extraPw.Result, + }, pulumi.Provider(pgProvider), withAlias()) + if err != nil { + return fmt.Errorf("failed to create %s role: %w", dbName, err) + } + + extraDb, err := postgresql.NewDatabase(ctx, fmt.Sprintf("%s-%s-db", name, dbName), &postgresql.DatabaseArgs{ + Name: pulumi.String(dbName), + Owner: pulumi.String(dbName), + }, pulumi.Provider(pgProvider), pulumi.DependsOn([]pulumi.Resource{extraRole}), pulumi.Protect(true), withAlias()) + if err != nil { + return fmt.Errorf("failed to create %s database: %w", dbName, err) + } + + _, err = postgresql.NewGrant(ctx, fmt.Sprintf("%s-%s-grant", name, dbName), &postgresql.GrantArgs{ + Database: pulumi.String(dbName), + Role: pulumi.String(dbName), + Schema: pulumi.String("public"), + ObjectType: pulumi.String("schema"), + Privileges: pulumi.StringArray{pulumi.String("CREATE"), pulumi.String("USAGE")}, + }, pulumi.Provider(pgProvider), pulumi.DependsOn([]pulumi.Resource{extraDb, extraRole}), withAlias()) + if err != nil { + return fmt.Errorf("failed to create %s grant: %w", dbName, err) + } + + ctx.Export(fmt.Sprintf("%s_pw", dbName), extraPw.Result) + } + + return nil +} + +// --- Azure deploy --- + +// azurePostgresConfigDeploy creates per-cluster Grafana PostgreSQL resources for Azure workloads. +// For each cluster release, it creates a password, role, database, grant, and a Key Vault secret +// containing the credentials. +func azurePostgresConfigDeploy(ctx *pulumi.Context, target types.Target, params azurePostgresParams) error { + name := target.Name() + + // Alias helpers for the two levels of Python component nesting: + // AzureWorkloadPostgresConfig -> provider + // AzureWorkloadPostgresConfig -> GrafanaPostgresResources -> per-cluster resources + outerComponentURN := fmt.Sprintf("urn:pulumi:%s::%s::ptd:AzureWorkloadPostgresConfig::%s", + ctx.Stack(), ctx.Project(), name) + + withProviderAlias := func() pulumi.ResourceOption { + return pulumi.Aliases([]pulumi.Alias{{ParentURN: pulumi.URN(outerComponentURN)}}) + } + + innerComponentURN := fmt.Sprintf("urn:pulumi:%s::%s::ptd:AzureWorkloadPostgresConfig$ptd:GrafanaPostgresResources::%s", + ctx.Stack(), ctx.Project(), name) + + withClusterAlias := func() pulumi.ResourceOption { + return pulumi.Aliases([]pulumi.Alias{{ParentURN: pulumi.URN(innerComponentURN)}}) + } + + // PostgreSQL provider pointing to Azure Database for PostgreSQL + pgProvider, err := postgresql.NewProvider(ctx, fmt.Sprintf("%s-grafana-postgres-provider", name), &postgresql.ProviderArgs{ + Host: pulumi.String(params.dbHost), + Port: pulumi.Int(5432), + Sslmode: pulumi.String("require"), + Username: pulumi.String(params.dbUser), + Password: pulumi.String(params.dbPassword), + Superuser: pulumi.Bool(false), + }, withProviderAlias()) + if err != nil { + return fmt.Errorf("failed to create postgres provider: %w", err) + } + + // Per-cluster Grafana resources + for _, release := range params.clusters { + releaseName := fmt.Sprintf("%s-%s", name, release) + grafanaRoleName := fmt.Sprintf("grafana-%s-%s", name, release) + grafanaDBName := grafanaRoleName + + // Random password + grafanaPw, err := random.NewRandomPassword(ctx, fmt.Sprintf("%s-db-grafana-pw", releaseName), &random.RandomPasswordArgs{ + Special: pulumi.Bool(true), + OverrideSpecial: pulumi.String("-_"), + Length: pulumi.Int(36), + }, withClusterAlias()) + if err != nil { + return fmt.Errorf("failed to create grafana password for %s: %w", release, err) + } + + // Grafana role + grafanaRole, err := postgresql.NewRole(ctx, fmt.Sprintf("%s-grafana-role", releaseName), &postgresql.RoleArgs{ + Login: pulumi.Bool(true), + Name: pulumi.String(grafanaRoleName), + Password: grafanaPw.Result, + }, pulumi.Provider(pgProvider), withClusterAlias()) + if err != nil { + return fmt.Errorf("failed to create grafana role for %s: %w", release, err) + } + + // Grafana database + grafanaDb, err := postgresql.NewDatabase(ctx, fmt.Sprintf("%s-grafana-db", releaseName), &postgresql.DatabaseArgs{ + Name: pulumi.String(grafanaDBName), + Owner: pulumi.String(grafanaRoleName), + }, pulumi.Provider(pgProvider), pulumi.DependsOn([]pulumi.Resource{grafanaRole}), pulumi.Protect(true), withClusterAlias()) + if err != nil { + return fmt.Errorf("failed to create grafana database for %s: %w", release, err) + } + + // Grafana grant + _, err = postgresql.NewGrant(ctx, fmt.Sprintf("%s-grafana-grant", releaseName), &postgresql.GrantArgs{ + Database: pulumi.String(grafanaDBName), + Role: pulumi.String(grafanaRoleName), + Schema: pulumi.String("public"), + ObjectType: pulumi.String("schema"), + Privileges: pulumi.StringArray{pulumi.String("CREATE"), pulumi.String("USAGE")}, + }, pulumi.Provider(pgProvider), pulumi.DependsOn([]pulumi.Resource{grafanaDb, grafanaRole}), withClusterAlias()) + if err != nil { + return fmt.Errorf("failed to create grafana grant for %s: %w", release, err) + } + + // Key Vault secret with credentials for this cluster's Grafana + secretValue := pulumi.All(grafanaPw.Result, pulumi.String(grafanaRoleName), pulumi.String(grafanaDBName)). + ApplyT(func(args []interface{}) (string, error) { + data := map[string]string{ + "password": args[0].(string), + "role": args[1].(string), + "database": args[2].(string), + } + bytes, err := json.Marshal(data) + if err != nil { + return "", err + } + return string(bytes), nil + }).(pulumi.StringOutput) + + _, err = keyvault.NewSecret(ctx, fmt.Sprintf("%s-postgres-grafana-user", releaseName), &keyvault.SecretArgs{ + SecretName: pulumi.String(fmt.Sprintf("%s-postgres-grafana-user", releaseName)), + ResourceGroupName: pulumi.String(params.resourceGroupName), + VaultName: pulumi.String(params.vaultName), + Properties: &keyvault.SecretPropertiesArgs{ + Value: secretValue, + }, + }, pulumi.Protect(params.protectPersistentResources)) + if err != nil { + return fmt.Errorf("failed to create Key Vault secret for %s: %w", release, err) + } + + // Export password (last cluster wins, matching Python behavior) + ctx.Export("db_grafana_pw", grafanaPw.Result) + } + return nil } diff --git a/lib/steps/postgres_config_test.go b/lib/steps/postgres_config_test.go new file mode 100644 index 0000000..af3947a --- /dev/null +++ b/lib/steps/postgres_config_test.go @@ -0,0 +1,337 @@ +package steps + +import ( + "context" + "testing" + + "github.com/pulumi/pulumi/sdk/v3/go/common/resource" + "github.com/pulumi/pulumi/sdk/v3/go/pulumi" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/posit-dev/ptd/lib/types" + "github.com/posit-dev/ptd/lib/types/typestest" +) + +func TestPostgresConfigStepName(t *testing.T) { + step := &PostgresConfigStep{} + assert.Equal(t, "postgres_config", step.Name()) +} + +func TestPostgresConfigStepProxyRequired(t *testing.T) { + step := &PostgresConfigStep{} + assert.True(t, step.ProxyRequired()) +} + +func TestPostgresConfigStepNilTarget(t *testing.T) { + step := &PostgresConfigStep{} + step.Set(nil, nil, StepOptions{}) + err := step.Run(context.Background()) + assert.ErrorContains(t, err, "postgres_config step requires a destination target") +} + +func TestParseDBSecretField(t *testing.T) { + t.Run("valid secret", func(t *testing.T) { + pw, err := parseDBSecretField(`{"password":"supersecret","username":"postgres"}`, "password") + require.NoError(t, err) + assert.Equal(t, "supersecret", pw) + }) + + t.Run("missing field", func(t *testing.T) { + pw, err := parseDBSecretField(`{"username":"postgres"}`, "password") + require.NoError(t, err) + assert.Equal(t, "", pw) + }) + + t.Run("invalid JSON", func(t *testing.T) { + _, err := parseDBSecretField(`not-json`, "password") + assert.Error(t, err) + }) +} + +// postgresConfigMocks implements pulumi.MockResourceMonitor for testing the deploy function. +type postgresConfigMocks struct { + resources []pulumi.MockResourceArgs +} + +func (m *postgresConfigMocks) NewResource(args pulumi.MockResourceArgs) (string, resource.PropertyMap, error) { + m.resources = append(m.resources, args) + return args.Name + "_id", args.Inputs, nil +} + +func (m *postgresConfigMocks) Call(args pulumi.MockCallArgs) (resource.PropertyMap, error) { + return resource.PropertyMap{}, nil +} + +func mockAWSTarget(name string, isControlRoom bool) *typestest.MockTarget { + tgt := &typestest.MockTarget{} + tgt.On("Name").Return(name) + tgt.On("CloudProvider").Return(types.AWS) + tgt.On("ControlRoom").Return(isControlRoom) + + if isControlRoom { + tgt.On("Type").Return(types.TargetTypeControlRoom) + } else { + tgt.On("Type").Return(types.TargetTypeWorkload) + } + + return tgt +} + +func mockAzureTarget(name string) *typestest.MockTarget { + tgt := &typestest.MockTarget{} + tgt.On("Name").Return(name) + tgt.On("CloudProvider").Return(types.Azure) + tgt.On("ControlRoom").Return(false) + tgt.On("Type").Return(types.TargetTypeWorkload) + return tgt +} + +// --- AWS deploy tests --- + +func TestAWSPostgresConfigDeployControlRoom(t *testing.T) { + mocks := &postgresConfigMocks{} + + err := pulumi.RunErr(func(ctx *pulumi.Context) error { + target := mockAWSTarget("test-aws-ctrl", true) + return awsPostgresConfigDeploy(ctx, target, "db.example.com", "master-pw", nil) + }, pulumi.WithMocks("ptd-aws-control-room-postgres-config", "test-aws-ctrl", mocks)) + + require.NoError(t, err) + + // Control room: 5 resources (password, provider, role, db, grant) + assert.Len(t, mocks.resources, 5, "control room should create exactly 5 resources") + + resourceNames := make([]string, len(mocks.resources)) + for i, r := range mocks.resources { + resourceNames[i] = r.Name + } + + assert.Contains(t, resourceNames, "test-aws-ctrl-db-grafana-pw") + assert.Contains(t, resourceNames, "test-aws-ctrl-postgres-provider") + assert.Contains(t, resourceNames, "test-aws-ctrl-grafana-role") + assert.Contains(t, resourceNames, "test-aws-ctrl-grafana-db") + assert.Contains(t, resourceNames, "test-aws-ctrl-grafana-grant") + + // Verify password length + for _, r := range mocks.resources { + if r.Name == "test-aws-ctrl-db-grafana-pw" { + assert.Equal(t, resource.NewNumberProperty(36), r.Inputs["length"]) + } + } + + // Verify role/db names use plain "grafana" for control room + for _, r := range mocks.resources { + if r.Name == "test-aws-ctrl-grafana-role" { + assert.Equal(t, resource.NewStringProperty("grafana"), r.Inputs["name"]) + } + if r.Name == "test-aws-ctrl-grafana-db" { + assert.Equal(t, resource.NewStringProperty("grafana"), r.Inputs["name"]) + } + } +} + +func TestAWSPostgresConfigDeployWorkload(t *testing.T) { + mocks := &postgresConfigMocks{} + + err := pulumi.RunErr(func(ctx *pulumi.Context) error { + target := mockAWSTarget("test-aws-staging", false) + return awsPostgresConfigDeploy(ctx, target, "db.example.com", "master-pw", nil) + }, pulumi.WithMocks("ptd-aws-workload-postgres-config", "test-aws-staging", mocks)) + + require.NoError(t, err) + + assert.Len(t, mocks.resources, 5, "workload should create exactly 5 resources") + + for _, r := range mocks.resources { + if r.Name == "test-aws-staging-grafana-role" { + assert.Equal(t, resource.NewStringProperty("grafana-test-aws-staging"), r.Inputs["name"]) + } + if r.Name == "test-aws-staging-grafana-db" { + assert.Equal(t, resource.NewStringProperty("grafana-test-aws-staging"), r.Inputs["name"]) + } + } +} + +func TestAWSPostgresConfigDeployWorkloadWithExtraDbs(t *testing.T) { + mocks := &postgresConfigMocks{} + + err := pulumi.RunErr(func(ctx *pulumi.Context) error { + target := mockAWSTarget("test-aws-staging", false) + return awsPostgresConfigDeploy(ctx, target, "db.example.com", "master-pw", []string{"soleng"}) + }, pulumi.WithMocks("ptd-aws-workload-postgres-config", "test-aws-staging", mocks)) + + require.NoError(t, err) + + // 5 base + 4 extra (pw, role, db, grant) = 9 + assert.Len(t, mocks.resources, 9, "workload with extra_postgres_dbs=[soleng] should create 9 resources") + + resourceNames := make([]string, len(mocks.resources)) + for i, r := range mocks.resources { + resourceNames[i] = r.Name + } + + assert.Contains(t, resourceNames, "test-aws-staging-db-soleng-pw") + assert.Contains(t, resourceNames, "test-aws-staging-soleng-role") + assert.Contains(t, resourceNames, "test-aws-staging-soleng-db") + assert.Contains(t, resourceNames, "test-aws-staging-soleng-grant") +} + +func TestAWSPostgresConfigDeployExtraDbHyphenSanitization(t *testing.T) { + mocks := &postgresConfigMocks{} + + err := pulumi.RunErr(func(ctx *pulumi.Context) error { + target := mockAWSTarget("test-aws-staging", false) + return awsPostgresConfigDeploy(ctx, target, "db.example.com", "master-pw", []string{"sol-eng"}) + }, pulumi.WithMocks("ptd-aws-workload-postgres-config", "test-aws-staging", mocks)) + + require.NoError(t, err) + + for _, r := range mocks.resources { + if r.Name == "test-aws-staging-sol_eng-role" { + assert.Equal(t, resource.NewStringProperty("sol_eng"), r.Inputs["name"]) + } + } +} + +func TestAWSPostgresConfigDeployProviderConfig(t *testing.T) { + mocks := &postgresConfigMocks{} + + err := pulumi.RunErr(func(ctx *pulumi.Context) error { + target := mockAWSTarget("test-aws-ctrl", true) + return awsPostgresConfigDeploy(ctx, target, "mydb.rds.amazonaws.com", "s3cret", nil) + }, pulumi.WithMocks("ptd-aws-control-room-postgres-config", "test-aws-ctrl", mocks)) + + require.NoError(t, err) + + for _, r := range mocks.resources { + if r.Name == "test-aws-ctrl-postgres-provider" { + assert.Equal(t, resource.NewStringProperty("mydb.rds.amazonaws.com"), r.Inputs["host"]) + assert.Equal(t, resource.NewNumberProperty(5432), r.Inputs["port"]) + assert.Equal(t, resource.NewStringProperty("require"), r.Inputs["sslmode"]) + assert.Equal(t, resource.NewStringProperty("postgres"), r.Inputs["username"]) + assert.Equal(t, resource.MakeSecret(resource.NewStringProperty("s3cret")), r.Inputs["password"]) + } + } +} + +// --- Azure deploy tests --- + +func TestAzurePostgresConfigDeploySingleCluster(t *testing.T) { + mocks := &postgresConfigMocks{} + + err := pulumi.RunErr(func(ctx *pulumi.Context) error { + target := mockAzureTarget("test-az-staging") + params := azurePostgresParams{ + dbHost: "db.postgres.azure.com", + dbUser: "adminuser", + dbPassword: "admin-pw", + clusters: []string{"20240101"}, + vaultName: "kv-ptd-test-az-staging", + resourceGroupName: "rsg-ptd-test-az-staging", + protectPersistentResources: false, + } + return azurePostgresConfigDeploy(ctx, target, params) + }, pulumi.WithMocks("ptd-azure-workload-postgres-config", "test-az-staging", mocks)) + + require.NoError(t, err) + + // 1 provider + 1 cluster * (pw + role + db + grant + kv secret) = 6 resources + assert.Len(t, mocks.resources, 6, "single cluster should create 6 resources") + + resourceNames := make([]string, len(mocks.resources)) + for i, r := range mocks.resources { + resourceNames[i] = r.Name + } + + assert.Contains(t, resourceNames, "test-az-staging-grafana-postgres-provider") + assert.Contains(t, resourceNames, "test-az-staging-20240101-db-grafana-pw") + assert.Contains(t, resourceNames, "test-az-staging-20240101-grafana-role") + assert.Contains(t, resourceNames, "test-az-staging-20240101-grafana-db") + assert.Contains(t, resourceNames, "test-az-staging-20240101-grafana-grant") + assert.Contains(t, resourceNames, "test-az-staging-20240101-postgres-grafana-user") + + // Verify role naming: grafana-{name}-{release} + for _, r := range mocks.resources { + if r.Name == "test-az-staging-20240101-grafana-role" { + assert.Equal(t, resource.NewStringProperty("grafana-test-az-staging-20240101"), r.Inputs["name"]) + } + } +} + +func TestAzurePostgresConfigDeployMultipleClusters(t *testing.T) { + mocks := &postgresConfigMocks{} + + err := pulumi.RunErr(func(ctx *pulumi.Context) error { + target := mockAzureTarget("test-az-staging") + params := azurePostgresParams{ + dbHost: "db.postgres.azure.com", + dbUser: "adminuser", + dbPassword: "admin-pw", + clusters: []string{"20240101", "20240201"}, + vaultName: "kv-ptd-test-az-staging", + resourceGroupName: "rsg-ptd-test-az-staging", + } + return azurePostgresConfigDeploy(ctx, target, params) + }, pulumi.WithMocks("ptd-azure-workload-postgres-config", "test-az-staging", mocks)) + + require.NoError(t, err) + + // 1 provider + 2 clusters * 5 resources = 11 + assert.Len(t, mocks.resources, 11, "two clusters should create 11 resources") +} + +func TestAzurePostgresConfigDeployProviderConfig(t *testing.T) { + mocks := &postgresConfigMocks{} + + err := pulumi.RunErr(func(ctx *pulumi.Context) error { + target := mockAzureTarget("test-az-staging") + params := azurePostgresParams{ + dbHost: "mydb.postgres.database.azure.com", + dbUser: "pgadmin", + dbPassword: "az-secret", + clusters: []string{"20240101"}, + vaultName: "kv-ptd-test-az-staging", + resourceGroupName: "rsg-ptd-test-az-staging", + } + return azurePostgresConfigDeploy(ctx, target, params) + }, pulumi.WithMocks("ptd-azure-workload-postgres-config", "test-az-staging", mocks)) + + require.NoError(t, err) + + for _, r := range mocks.resources { + if r.Name == "test-az-staging-grafana-postgres-provider" { + assert.Equal(t, resource.NewStringProperty("mydb.postgres.database.azure.com"), r.Inputs["host"]) + assert.Equal(t, resource.NewStringProperty("pgadmin"), r.Inputs["username"]) + assert.Equal(t, resource.MakeSecret(resource.NewStringProperty("az-secret")), r.Inputs["password"]) + } + } +} + +func TestAzurePostgresConfigDeployKeyVaultSecret(t *testing.T) { + mocks := &postgresConfigMocks{} + + err := pulumi.RunErr(func(ctx *pulumi.Context) error { + target := mockAzureTarget("test-az-staging") + params := azurePostgresParams{ + dbHost: "db.postgres.azure.com", + dbUser: "adminuser", + dbPassword: "admin-pw", + clusters: []string{"20240101"}, + vaultName: "kv-ptd-test-az-staging", + resourceGroupName: "rsg-ptd-test-az-staging", + } + return azurePostgresConfigDeploy(ctx, target, params) + }, pulumi.WithMocks("ptd-azure-workload-postgres-config", "test-az-staging", mocks)) + + require.NoError(t, err) + + // Verify the Key Vault secret resource + for _, r := range mocks.resources { + if r.Name == "test-az-staging-20240101-postgres-grafana-user" { + assert.Equal(t, resource.NewStringProperty("test-az-staging-20240101-postgres-grafana-user"), r.Inputs["secretName"]) + assert.Equal(t, resource.NewStringProperty("kv-ptd-test-az-staging"), r.Inputs["vaultName"]) + assert.Equal(t, resource.NewStringProperty("rsg-ptd-test-az-staging"), r.Inputs["resourceGroupName"]) + } + } +} diff --git a/lib/testdata/infra/__ctrl__/test-aws-ctrl/ptd.yaml b/lib/testdata/infra/__ctrl__/test-aws-ctrl/ptd.yaml new file mode 100644 index 0000000..393a598 --- /dev/null +++ b/lib/testdata/infra/__ctrl__/test-aws-ctrl/ptd.yaml @@ -0,0 +1,7 @@ +apiVersion: posit.team/v1 +kind: AWSControlRoomConfig +metadata: + name: test-aws-ctrl +spec: + region: us-east-2 + account_id: "123456789012" diff --git a/lib/testdata/infra/__work__/test-aws-basic/ptd.yaml b/lib/testdata/infra/__work__/test-aws-basic/ptd.yaml new file mode 100644 index 0000000..023cd26 --- /dev/null +++ b/lib/testdata/infra/__work__/test-aws-basic/ptd.yaml @@ -0,0 +1,7 @@ +apiVersion: posit.team/v1 +kind: AWSWorkloadConfig +metadata: + name: test-aws-basic +spec: + region: us-east-2 + account_id: "123456789012" diff --git a/lib/testdata/infra/__work__/test-aws-staging/ptd.yaml b/lib/testdata/infra/__work__/test-aws-staging/ptd.yaml new file mode 100644 index 0000000..3957faf --- /dev/null +++ b/lib/testdata/infra/__work__/test-aws-staging/ptd.yaml @@ -0,0 +1,9 @@ +apiVersion: posit.team/v1 +kind: AWSWorkloadConfig +metadata: + name: test-aws-staging +spec: + region: us-east-2 + account_id: "123456789012" + extra_postgres_dbs: + - soleng diff --git a/python-pulumi/src/ptd/pulumi_resources/aws_control_room_postgres_config.py b/python-pulumi/src/ptd/pulumi_resources/aws_control_room_postgres_config.py deleted file mode 100644 index 13f4ca0..0000000 --- a/python-pulumi/src/ptd/pulumi_resources/aws_control_room_postgres_config.py +++ /dev/null @@ -1,120 +0,0 @@ -import json - -import pulumi -import pulumi_aws as aws -import pulumi_postgresql -import pulumi_random - -import ptd.aws_control_room - - -class AWSControlRoomPostgresConfig(pulumi.ComponentResource): - control_room: ptd.aws_control_room.AWSControlRoom - grafana_db: pulumi_postgresql.Database - grant: pulumi_postgresql.Grant - db_host_output: pulumi.Output - - @classmethod - def autoload(cls) -> "AWSControlRoomPostgresConfig": - return cls(ptd.aws_control_room.AWSControlRoom(pulumi.get_stack())) - - def __init__(self, control_room: ptd.aws_control_room.AWSControlRoom, *args, **kwargs): - super().__init__( - f"ptd:{self.__class__.__name__}", - control_room.compound_name, - *args, - **kwargs, - ) - self.control_room = control_room - self.name = self.control_room.compound_name - self.required_tags = self.control_room.required_tags | {str(ptd.TagKeys.POSIT_TEAM_MANAGED_BY): __name__} - - self._define_grafana() - - outputs = { - "db_grafana_connection": pulumi.Output.format( - "postgres://grafana:{0}@{1}/grafana", - self.db_grafana_pw.result, - self.db_host_output, - ), - "db_grafana_pw": self.db_grafana_pw.result, - "grafana_db_name": self.grafana_db.name, - "grant_id": self.grant.id, - } - - for key, value in outputs.items(): - pulumi.export(key, value) - - self.register_outputs(outputs) - - def _define_grafana(self) -> None: - persistent_stack = pulumi.StackReference( - f"organization/ptd-aws-control-room-persistent/{self.control_room.compound_name}" - ) - self.db_host_output = persistent_stack.require_output("db_address") - db_port = 5432 # probably shouldn't hardcode this. - db_secret_arn_output = persistent_stack.require_output("db_secret_arn") - secret_version = aws.secretsmanager.get_secret_version(secret_id=db_secret_arn_output.apply(lambda x: x)) - - pw = json.loads(secret_version.secret_string).get("password", "") - - self.db_grafana_pw = pulumi_random.RandomPassword( - f"{self.name}-db-grafana-pw", - special=True, - override_special="-_", - length=36, - opts=pulumi.ResourceOptions(parent=self), - ) - - postgres = pulumi_postgresql.provider.Provider( - f"{self.name}-postgres-provider", - host=self.db_host_output.apply(lambda x: x), - port=db_port, - sslmode="require", - username="postgres", - password=pw, - superuser=False, - opts=pulumi.ResourceOptions( - parent=self, - ), - ) - - grafana_role = pulumi_postgresql.Role( - f"{self.name}-grafana-role", - login=True, - name="grafana", - password=self.db_grafana_pw.result, - opts=pulumi.ResourceOptions( - provider=postgres, - parent=self, - ), - ) - - self.grafana_db = pulumi_postgresql.Database( - f"{self.name}-grafana-db", - name="grafana", - owner="grafana", - opts=pulumi.ResourceOptions( - provider=postgres, - parent=self, - depends_on=[grafana_role], - ), - ) - - self.grant = pulumi_postgresql.Grant( - f"{self.name}-grafana-grant", - database="grafana", - role="grafana", - schema="public", - object_type="schema", - privileges=[ - "CREATE", - "USAGE", - ], - opts=pulumi.ResourceOptions( - provider=postgres, - parent=self, - depends_on=[self.grafana_db, grafana_role], - protect=False, - ), - ) diff --git a/python-pulumi/src/ptd/pulumi_resources/aws_workload_postgres_config.py b/python-pulumi/src/ptd/pulumi_resources/aws_workload_postgres_config.py deleted file mode 100644 index 68f9e33..0000000 --- a/python-pulumi/src/ptd/pulumi_resources/aws_workload_postgres_config.py +++ /dev/null @@ -1,182 +0,0 @@ -import json - -import pulumi -import pulumi_aws as aws -import pulumi_postgresql -import pulumi_random - -import ptd -import ptd.aws_workload -import ptd.paths -import ptd.pulumi_resources.aws_fsx_openzfs_multi -import ptd.pulumi_resources.aws_vpc - - -class AWSWorkloadPostgresConfig(pulumi.ComponentResource): - postgres: pulumi_postgresql.provider.Provider - workload: ptd.aws_workload.AWSWorkload - extra_db_pws: dict[str, pulumi_random.RandomPassword] - - @classmethod - def autoload(cls) -> "AWSWorkloadPostgresConfig": - return cls(workload=ptd.aws_workload.AWSWorkload(pulumi.get_stack())) - - def __init__( - self, - workload: ptd.aws_workload.AWSWorkload, - *args, - **kwargs, - ): - super().__init__( - f"ptd:{self.__class__.__name__}", - workload.compound_name, - *args, - **kwargs, - ) - - self.extra_db_pws = {} - self.workload = workload - - self._define_provider() - self._define_grafana() - self._define_extra_dbs() - - outputs = { - "db_grafana_pw": self.db_grafana_pw.result, - "grafana_db_name": self.grafana_db.name, - "grant_id": self.grant.id, - } - - for db_name, pw in self.extra_db_pws.items(): - outputs[f"{db_name}_pw"] = pw.result - - for key, value in outputs.items(): - pulumi.export(key, value) - - self.register_outputs(outputs) - - def _define_provider(self) -> None: - persistent_stack = pulumi.StackReference( - f"organization/ptd-aws-workload-persistent/{self.workload.compound_name}" - ) - db_host_output = persistent_stack.require_output("db_address") - db_port = 5432 # probably shouldn't hardcode this. - db_secret_arn_output = persistent_stack.require_output("db_secret_arn") - secret_version = aws.secretsmanager.get_secret_version(secret_id=db_secret_arn_output.apply(lambda x: x)) - - pw = json.loads(secret_version.secret_string).get("password", "") - - self.postgres = pulumi_postgresql.provider.Provider( - f"{self.workload.compound_name}-postgres-provider", - host=db_host_output.apply(lambda x: x), - port=db_port, - sslmode="require", - username="postgres", - password=pw, - superuser=False, - opts=pulumi.ResourceOptions( - parent=self, - ), - ) - - def _define_grafana(self) -> None: - self.db_grafana_pw = pulumi_random.RandomPassword( - f"{self.workload.compound_name}-db-grafana-pw", - special=True, - override_special="-_", - length=36, - opts=pulumi.ResourceOptions(parent=self), - ) - - role = database = f"grafana-{self.workload.compound_name}" - - grafana_role = pulumi_postgresql.Role( - f"{self.workload.compound_name}-grafana-role", - login=True, - name=role, - password=self.db_grafana_pw.result, - opts=pulumi.ResourceOptions( - provider=self.postgres, - parent=self, - ), - ) - - self.grafana_db = pulumi_postgresql.Database( - f"{self.workload.compound_name}-grafana-db", - name=database, - owner=role, - opts=pulumi.ResourceOptions( - provider=self.postgres, - parent=self, - depends_on=[grafana_role], - protect=True, - ), - ) - - self.grant = pulumi_postgresql.Grant( - f"{self.workload.compound_name}-grafana-grant", - database=database, - role=role, - schema="public", - object_type="schema", - privileges=[ - "CREATE", - "USAGE", - ], - opts=pulumi.ResourceOptions( - provider=self.postgres, - parent=self, - depends_on=[self.grafana_db, grafana_role], - ), - ) - - def _define_extra_dbs(self) -> None: - for dbn in self.workload.cfg.extra_postgres_dbs: - db_name = dbn.replace("-", "_") - - pw = pulumi_random.RandomPassword( - f"{self.workload.compound_name}-db-{db_name}-pw", - special=True, - override_special="-_", - length=36, - opts=pulumi.ResourceOptions(parent=self), - ) - - self.extra_db_pws[db_name] = pw - - role = pulumi_postgresql.Role( - f"{self.workload.compound_name}-{db_name}-role", - login=True, - name=db_name, - password=pw.result, - opts=pulumi.ResourceOptions( - provider=self.postgres, - parent=self, - ), - ) - - db = pulumi_postgresql.Database( - f"{self.workload.compound_name}-{db_name}-db", - name=db_name, - owner=role, - opts=pulumi.ResourceOptions( - provider=self.postgres, - parent=self, - depends_on=[role], - protect=True, - ), - ) - - pulumi_postgresql.Grant( - f"{self.workload.compound_name}-{db_name}-grant", - database=db_name, - role=role, - schema="public", - object_type="schema", - privileges=["CREATE", "USAGE"], - opts=pulumi.ResourceOptions( - provider=self.postgres, - parent=self, - depends_on=[db, role], - ), - ) diff --git a/python-pulumi/src/ptd/pulumi_resources/azure_workload_postgres_config.py b/python-pulumi/src/ptd/pulumi_resources/azure_workload_postgres_config.py deleted file mode 100644 index de3f7c8..0000000 --- a/python-pulumi/src/ptd/pulumi_resources/azure_workload_postgres_config.py +++ /dev/null @@ -1,98 +0,0 @@ -import json - -import pulumi -import pulumi_azure_native as pulumi_az -import pulumi_postgresql - -import ptd.azure_workload -from ptd import azure_sdk -from ptd.pulumi_resources.grafana_postgres_resources import GrafanaPostgresResources - - -class AzureWorkloadPostgresConfig(pulumi.ComponentResource): - provider: pulumi_postgresql.provider.Provider - workload: ptd.azure_workload.AzureWorkload - - @classmethod - def autoload(cls) -> "AzureWorkloadPostgresConfig": - return cls(workload=ptd.azure_workload.AzureWorkload(pulumi.get_stack())) - - def __init__( - self, - workload: ptd.azure_workload.AzureWorkload, - *args, - **kwargs, - ): - super().__init__( - f"ptd:{self.__class__.__name__}", - workload.compound_name, - *args, - **kwargs, - ) - - self.workload = workload - - self._define_provider() - self._define_grafana_resources() - - def _define_provider(self) -> None: - # fetch secret created via persistent step - secret = azure_sdk.get_secret_json( - secret_name=f"{self.workload.compound_name}-grafana-postgres-admin-secret", - vault_name=self.workload.key_vault_name, - ) - - fqdn = secret.get("fqdn") - user = secret.get("username") - pw = secret.get("password") - - if not fqdn or not user or not pw: - msg = "Grafana DB secret must contain 'fqdn', 'username' and 'password' fields." - raise ValueError(msg) - - self.provider = pulumi_postgresql.provider.Provider( - f"{self.workload.compound_name}-grafana-postgres-provider", - host=fqdn, - port=5432, - sslmode="require", - username=user, - password=pw, - superuser=False, - opts=pulumi.ResourceOptions( - parent=self, - ), - ) - - def _define_grafana_resources(self): - for release in self.workload.cfg.clusters: - postgres = GrafanaPostgresResources( - workload=self.workload, - release=release, - opts=pulumi.ResourceOptions( - parent=self, - provider=self.provider, - ), - ) - - secret_val = pulumi.Output.all( - pw=postgres.password.result, role=postgres.role, database=postgres.database - ).apply( - lambda outputs: json.dumps( - { - "role": outputs["role"], - "database": outputs["database"], - "password": outputs["pw"], - } - ) - ) - - pulumi_az.keyvault.Secret( - f"{self.workload.compound_name}-{release}-postgres-grafana-user", - secret_name=f"{self.workload.compound_name}-{release}-postgres-grafana-user", - resource_group_name=self.workload.resource_group_name, - properties=pulumi_az.keyvault.SecretPropertiesArgs(value=secret_val), - vault_name=self.workload.key_vault_name, - opts=pulumi.ResourceOptions( - protect=self.workload.cfg.protect_persistent_resources, - ), - ) diff --git a/python-pulumi/src/ptd/pulumi_resources/grafana_postgres_resources.py b/python-pulumi/src/ptd/pulumi_resources/grafana_postgres_resources.py deleted file mode 100644 index 70a8428..0000000 --- a/python-pulumi/src/ptd/pulumi_resources/grafana_postgres_resources.py +++ /dev/null @@ -1,92 +0,0 @@ -import pulumi -import pulumi_postgresql -import pulumi_random - -import ptd.workload - - -class GrafanaPostgresResources(pulumi.ComponentResource): - provider: pulumi_postgresql.provider.Provider - workload: ptd.workload.AbstractWorkload - release: str - - role: str - database: str - password: pulumi_random.RandomPassword - - def __init__( - self, - workload: ptd.workload.AbstractWorkload, - release: str, - *args, - **kwargs, - ): - super().__init__( - f"ptd:{self.__class__.__name__}", - workload.compound_name, - *args, - **kwargs, - ) - - self.workload = workload - self.release = release - - self._define_grafana() - - outputs = { - "db_grafana_pw": self.password.result, - } - - for key, value in outputs.items(): - pulumi.export(key, value) - - self.register_outputs(outputs) - - def _define_grafana(self) -> None: - name = f"{self.workload.compound_name}-{self.release}" - self.password = pulumi_random.RandomPassword( - f"{name}-db-grafana-pw", - special=True, - override_special="-_", - length=36, - opts=pulumi.ResourceOptions(parent=self), - ) - - self.role = self.database = f"grafana-{self.workload.compound_name}-{self.release}" - - grafana_role = pulumi_postgresql.Role( - f"{name}-grafana-role", - login=True, - name=self.role, - password=self.password.result, - opts=pulumi.ResourceOptions( - parent=self, - ), - ) - - self.grafana_db = pulumi_postgresql.Database( - f"{name}-grafana-db", - name=self.database, - owner=self.role, - opts=pulumi.ResourceOptions( - parent=self, - depends_on=[grafana_role], - protect=True, - ), - ) - - self.grant = pulumi_postgresql.Grant( - f"{name}-grafana-grant", - database=self.database, - role=self.role, - schema="public", - object_type="schema", - privileges=[ - "CREATE", - "USAGE", - ], - opts=pulumi.ResourceOptions( - parent=self, - depends_on=[self.grafana_db, grafana_role], - ), - ) diff --git a/python-pulumi/tests/test_stub_import_only.py b/python-pulumi/tests/test_stub_import_only.py index 7a76682..9311818 100644 --- a/python-pulumi/tests/test_stub_import_only.py +++ b/python-pulumi/tests/test_stub_import_only.py @@ -14,13 +14,11 @@ import ptd.pulumi_resources.aws_bastion import ptd.pulumi_resources.aws_control_room_cluster import ptd.pulumi_resources.aws_control_room_persistent -import ptd.pulumi_resources.aws_control_room_postgres_config import ptd.pulumi_resources.aws_eks_cluster import ptd.pulumi_resources.aws_fsx_openzfs_multi import ptd.pulumi_resources.aws_vpc import ptd.pulumi_resources.aws_workload_clusters import ptd.pulumi_resources.aws_workload_persistent -import ptd.pulumi_resources.aws_workload_postgres_config import ptd.pulumi_resources.external_dns import ptd.pulumi_resources.grafana_alloy import ptd.pulumi_resources.keycloak_operator @@ -51,13 +49,11 @@ def test_import_only() -> None: assert ptd.pulumi_resources.aws_bastion is not None assert ptd.pulumi_resources.aws_control_room_cluster is not None assert ptd.pulumi_resources.aws_control_room_persistent is not None - assert ptd.pulumi_resources.aws_control_room_postgres_config is not None assert ptd.pulumi_resources.aws_eks_cluster is not None assert ptd.pulumi_resources.aws_fsx_openzfs_multi is not None assert ptd.pulumi_resources.aws_vpc is not None assert ptd.pulumi_resources.aws_workload_clusters is not None assert ptd.pulumi_resources.aws_workload_persistent is not None - assert ptd.pulumi_resources.aws_workload_postgres_config is not None assert ptd.pulumi_resources.external_dns is not None assert ptd.pulumi_resources.grafana_alloy is not None assert ptd.pulumi_resources.keycloak_operator is not None