diff --git a/cmd/describe_affected.go b/cmd/describe_affected.go
new file mode 100644
index 000000000..1f611079f
--- /dev/null
+++ b/cmd/describe_affected.go
@@ -0,0 +1,34 @@
+package cmd
+
+import (
+ "github.com/spf13/cobra"
+
+ e "github.com/cloudposse/atmos/internal/exec"
+ u "github.com/cloudposse/atmos/pkg/utils"
+)
+
+// describeAffectedCmd produces a list of the affected Atmos components and stacks given two Git commits
+var describeAffectedCmd = &cobra.Command{
+ Use: "affected",
+ Short: "Execute 'describe affected' command",
+ Long: `This command produces a list of the affected Atmos components and stacks given two Git commits: atmos describe stacks [options]`,
+ FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: true},
+ Run: func(cmd *cobra.Command, args []string) {
+ err := e.ExecuteDescribeAffectedCmd(cmd, args)
+ if err != nil {
+ u.PrintErrorToStdErrorAndExit(err)
+ }
+ },
+}
+
+func init() {
+ describeAffectedCmd.DisableFlagParsing = false
+
+ describeAffectedCmd.PersistentFlags().String("ref", "", "Git reference with which to compare the current branch: atmos describe affected --ref refs/heads/main. Refer to https://git-scm.com/book/en/v2/Git-Internals-Git-References for more details")
+ describeAffectedCmd.PersistentFlags().String("sha", "", "Git commit SHA with which to compare the current branch: atmos describe affected --sha 3a5eafeab90426bd82bf5899896b28cc0bab3073")
+ describeAffectedCmd.PersistentFlags().String("file", "", "Write the result to the file: atmos describe affected --ref refs/tags/v1.16.0 --file affected.json")
+ describeAffectedCmd.PersistentFlags().String("format", "json", "The output format: atmos describe affected --format=json|yaml ('json' is default)")
+ describeAffectedCmd.PersistentFlags().Bool("verbose", false, "Print more detailed output when cloning and checking out the Git repository: atmos describe affected --verbose=true")
+
+ describeCmd.AddCommand(describeAffectedCmd)
+}
diff --git a/examples/complete/Dockerfile b/examples/complete/Dockerfile
index f5d6e4a2e..c460fe25d 100644
--- a/examples/complete/Dockerfile
+++ b/examples/complete/Dockerfile
@@ -1,10 +1,10 @@
# Geodesic: https://github.com/cloudposse/geodesic/
-ARG GEODESIC_VERSION=1.3.2
+ARG GEODESIC_VERSION=1.6.0
ARG GEODESIC_OS=debian
# atmos: https://github.com/cloudposse/atmos
-ARG ATMOS_VERSION=1.9.0
+ARG ATMOS_VERSION=1.17.0
# Terraform: https://github.com/hashicorp/terraform/releases
-ARG TF_VERSION=1.3.0
+ARG TF_VERSION=1.3.6
FROM cloudposse/geodesic:${GEODESIC_VERSION}-${GEODESIC_OS}
diff --git a/go.mod b/go.mod
index 9e7f5fefb..bd81eea00 100644
--- a/go.mod
+++ b/go.mod
@@ -5,6 +5,7 @@ go 1.19
require (
github.com/bmatcuk/doublestar/v4 v4.4.0
github.com/fatih/color v1.13.0
+ github.com/go-git/go-git/v5 v5.5.1
github.com/hashicorp/go-getter v1.6.2
github.com/hashicorp/hcl v1.0.0
github.com/hashicorp/hcl/v2 v2.15.0
@@ -12,7 +13,7 @@ require (
github.com/json-iterator/go v1.1.12
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/mapstructure v1.5.0
- github.com/open-policy-agent/opa v0.46.1
+ github.com/open-policy-agent/opa v0.47.3
github.com/otiai10/copy v1.9.0
github.com/pkg/errors v0.9.1
github.com/santhosh-tekuri/jsonschema/v5 v5.1.1
@@ -21,7 +22,7 @@ require (
github.com/stretchr/testify v1.8.1
github.com/zclconf/go-cty v1.12.1
gopkg.in/yaml.v2 v2.4.0
- mvdan.cc/sh/v3 v3.5.1
+ mvdan.cc/sh/v3 v3.6.0
)
require (
@@ -31,16 +32,20 @@ require (
cloud.google.com/go/iam v0.3.0 // indirect
cloud.google.com/go/storage v1.23.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
+ github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/OneOfOne/xxhash v1.2.8 // indirect
+ github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 // indirect
+ github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/agext/levenshtein v1.2.1 // indirect
github.com/agnivade/levenshtein v1.1.1 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/aws/aws-sdk-go v1.15.78 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
- github.com/bytecodealliance/wasmtime-go v1.0.0 // indirect
+ github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
- github.com/containerd/containerd v1.6.9 // indirect
+ github.com/cloudflare/circl v1.1.0 // indirect
+ github.com/containerd/containerd v1.6.10 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/cli v20.10.17+incompatible // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
@@ -49,8 +54,11 @@ require (
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-metrics v0.0.1 // indirect
github.com/docker/go-units v0.4.0 // indirect
+ github.com/emirpasic/gods v1.18.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
+ github.com/go-git/gcfg v1.5.0 // indirect
+ github.com/go-git/go-billy/v5 v5.3.1 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
@@ -68,7 +76,9 @@ require (
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-version v1.1.0 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
+ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 // indirect
+ github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
@@ -85,13 +95,16 @@ require (
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
+ github.com/pjbgf/sha1cd v0.2.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/prometheus/client_golang v1.13.1 // indirect
- github.com/prometheus/client_model v0.2.0 // indirect
+ github.com/prometheus/client_golang v1.14.0 // indirect
+ github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
+ github.com/sergi/go-diff v1.1.0 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
+ github.com/skeema/knownhosts v1.1.0 // indirect
github.com/spf13/afero v1.9.2 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
@@ -99,6 +112,7 @@ require (
github.com/subosito/gotenv v1.4.1 // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
github.com/ulikunitz/xz v0.5.8 // indirect
+ github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/yashtewari/glob-intersection v0.1.0 // indirect
@@ -106,20 +120,22 @@ require (
go.opentelemetry.io/otel v1.7.0 // indirect
go.opentelemetry.io/otel/sdk v1.7.0 // indirect
go.opentelemetry.io/otel/trace v1.7.0 // indirect
- golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect
+ golang.org/x/crypto v0.3.0 // indirect
+ golang.org/x/net v0.4.0 // indirect
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
golang.org/x/sync v0.1.0 // indirect
- golang.org/x/sys v0.0.0-20221010170243-090e33056c14 // indirect
- golang.org/x/text v0.4.0 // indirect
+ golang.org/x/sys v0.3.0 // indirect
+ golang.org/x/term v0.3.0 // indirect
+ golang.org/x/text v0.5.0 // indirect
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
- golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.102.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e // indirect
- google.golang.org/grpc v1.50.1 // indirect
+ google.golang.org/grpc v1.51.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
+ gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
oras.land/oras-go v1.2.1 // indirect
)
diff --git a/go.sum b/go.sum
index b0f87963b..d09fac4d8 100644
--- a/go.sum
+++ b/go.sum
@@ -73,11 +73,16 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg6
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
-github.com/Microsoft/hcsshim v0.9.4 h1:mnUj0ivWy6UzbB1uLFqKR6F+ZyiDc7j4iGgHTpO+5+I=
+github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
+github.com/Microsoft/hcsshim v0.9.5 h1:AbV+VPfTrIVffukazHcpxmz/sRiE6YaMDzHWR9BXZHo=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
+github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 h1:ra2OtmuW0AE5csawV4YXMNGNQQXvLRps3z2Z59OPO+I=
+github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
+github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
+github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
@@ -87,11 +92,15 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
+github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
+github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/aws/aws-sdk-go v1.15.78 h1:LaXy6lWR0YK7LKyuU0QWy2ws/LWTPfYV/UgfiBu4tvY=
github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -106,8 +115,9 @@ github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuP
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng=
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ=
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o=
-github.com/bytecodealliance/wasmtime-go v1.0.0 h1:9u9gqaUiaJeN5IoD1L7egD8atOnTGyJcNp8BhkL9cUU=
-github.com/bytecodealliance/wasmtime-go v1.0.0/go.mod h1:jjlqQbWUfVSbehpErw3UoWFndBXRRMvfikYH6KsCwOg=
+github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
+github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA=
+github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q=
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
@@ -120,6 +130,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cloudflare/circl v1.1.0 h1:bZgT/A+cikZnKIwn7xL2OBj012Bmvho/o6RpRvv3GKY=
+github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@@ -130,16 +142,17 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4=
-github.com/containerd/containerd v1.6.9 h1:IN/r8DUes/B5lEGTNfIiUkfZBtIQJGx2ai703dV6lRA=
-github.com/containerd/containerd v1.6.9/go.mod h1:XVicUvkxOrftE2Q1YWUXgZwkkAxwQYNOFzYWvfVfEfQ=
+github.com/containerd/containerd v1.6.10 h1:8aiav7I2ZyQLbTlNMcBXyAU1FtFvp6VuyuW13qSd6Hk=
+github.com/containerd/containerd v1.6.10/go.mod h1:CVqfxdJ95PDgORwA219AwwLrREZgrTFybXu2HfMKRG0=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dgraph-io/badger/v3 v3.2103.3 h1:s63J1pisDhKpzWslXFe+ChuthuZptpwTE6qEKoczPb4=
+github.com/dgraph-io/badger/v3 v3.2103.4 h1:WE1B07YNTTJTtG9xjBcSW2wn0RJLyiV99h959RKZqM4=
github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8=
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g=
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
@@ -161,6 +174,8 @@ github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
+github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
+github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@@ -177,11 +192,21 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF
github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/foxcpp/go-mockdns v0.0.0-20210729171921-fb145fc6f897 h1:E52jfcE64UG42SwLmrW0QByONfGynWuzBvm86BoB9z8=
-github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
+github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
+github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
+github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
+github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
+github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34=
+github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-git-fixtures/v4 v4.3.1 h1:y5z6dd3qi8Hl+stezc8p3JxDkoTRqMAlKnXHuzrfjTQ=
+github.com/go-git/go-git-fixtures/v4 v4.3.1/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo=
+github.com/go-git/go-git/v5 v5.5.1 h1:5vtv2TB5PM/gPM+EvsHJ16hJh4uAkdGcKilcwY7FYwo=
+github.com/go-git/go-git/v5 v5.5.1/go.mod h1:uz5PQ3d0gz7mSgzZhSJToM6ALPaKCdSnl58/Xb5hzr8=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -331,6 +356,9 @@ github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
@@ -344,6 +372,8 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
+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/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.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
@@ -354,13 +384,17 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
+github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
+github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
@@ -399,8 +433,9 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/open-policy-agent/opa v0.46.1 h1:iG998SLK0rzalex7Hyekeq17b9WtUexM0AuyHrQ7fCc=
-github.com/open-policy-agent/opa v0.46.1/go.mod h1:DY9ZkCyz+DKoWI5gDuLw5rGC2RSb37QUeEf+9VjsWkI=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/open-policy-agent/opa v0.47.3 h1:Uj8zw+q6Cvv1iiQFh704Q6sl3fKVvk35WZNJLsd6mgk=
+github.com/open-policy-agent/opa v0.47.3/go.mod h1:I5DbT677OGqfk9gvu5i54oIt0rrVf4B5pedpqDquAXo=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec=
@@ -417,6 +452,8 @@ github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko
github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
+github.com/pjbgf/sha1cd v0.2.3 h1:uKQP/7QOzNtKYH7UTohZLcjF5/55EnTw0jO/Ru4jZwI=
+github.com/pjbgf/sha1cd v0.2.3/go.mod h1:HOK9QrgzdHpbc2Kzip0Q1yi3M2MFGPADtR6HjG65m5M=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -430,13 +467,14 @@ github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQ
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
-github.com/prometheus/client_golang v1.13.1 h1:3gMjIY2+/hzmqhtUC/aQNYldJA6DtH3CgQvwS+02K1c=
-github.com/prometheus/client_golang v1.13.1/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
+github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
+github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
+github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
@@ -456,16 +494,20 @@ github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
+github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/santhosh-tekuri/jsonschema/v5 v5.1.1 h1:lEOLY2vyGIqKWUI9nzsOJRV3mb3WC9dXYORsLEUcoeY=
github.com/santhosh-tekuri/jsonschema/v5 v5.1.1/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
+github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
+github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0=
+github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=
github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
@@ -500,6 +542,8 @@ github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BG
github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
+github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
+github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
@@ -511,6 +555,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI=
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY=
@@ -544,8 +589,13 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
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-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
+golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
+golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -581,6 +631,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -620,6 +671,7 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
@@ -627,8 +679,11 @@ golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU=
-golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
+golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
+golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
+golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -663,6 +718,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -679,6 +735,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -725,6 +782,7 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -741,12 +799,19 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20221010170243-090e33056c14 h1:k5II8e6QD8mITdi+okbbmR/cIyEbeXLBhy5Ha4nevyc=
-golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
+golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
+golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
+golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -756,8 +821,9 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
+golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -818,6 +884,7 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
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=
@@ -991,8 +1058,8 @@ google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
-google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
+google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
+google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@@ -1014,11 +1081,15 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -1040,8 +1111,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-mvdan.cc/sh/v3 v3.5.1 h1:hmP3UOw4f+EYexsJjFxvU38+kn+V/s2CclXHanIBkmQ=
-mvdan.cc/sh/v3 v3.5.1/go.mod h1:1JcoyAKm1lZw/2bZje/iYKWicU/KMd0rsyJeKHnsK4E=
+mvdan.cc/sh/v3 v3.6.0 h1:gtva4EXJ0dFNvl5bHjcUEvws+KRcDslT8VKheTYkbGU=
+mvdan.cc/sh/v3 v3.6.0/go.mod h1:U4mhtBLZ32iWhif5/lD+ygy1zrgaQhUu+XFy7C8+TTA=
oras.land/oras-go v1.2.1 h1:/VcGS8FUy3eEXLl/1vC4QypLHwrfSmgW7ygsoklqKK8=
oras.land/oras-go v1.2.1/go.mod h1:3N11Z5E3c4ZzOjroCl1RtAdB4yNAYl7A27j2SVf913A=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go
new file mode 100644
index 000000000..9f04fe689
--- /dev/null
+++ b/internal/exec/describe_affected.go
@@ -0,0 +1,510 @@
+package exec
+
+import (
+ "fmt"
+ cfg "github.com/cloudposse/atmos/pkg/config"
+ u "github.com/cloudposse/atmos/pkg/utils"
+ "github.com/go-git/go-git/v5"
+ "github.com/go-git/go-git/v5/plumbing"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+ "os"
+ "path"
+ "reflect"
+ "strconv"
+ "time"
+)
+
+// ExecuteDescribeAffectedCmd executes `describe affected` command
+func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error {
+ info, err := processCommandLineArgs("", cmd, args)
+ if err != nil {
+ return err
+ }
+
+ cliConfig, err := cfg.InitCliConfig(info, true)
+ if err != nil {
+ u.PrintErrorToStdError(err)
+ return err
+ }
+
+ // Process flags
+ flags := cmd.Flags()
+
+ ref, err := flags.GetString("ref")
+ if err != nil {
+ return err
+ }
+
+ sha, err := flags.GetString("sha")
+ if err != nil {
+ return err
+ }
+
+ format, err := flags.GetString("format")
+ if err != nil {
+ return err
+ }
+
+ if format != "" && format != "yaml" && format != "json" {
+ return fmt.Errorf("invalid '--format' flag '%s'. Valid values are 'json' (default) and 'yaml'", format)
+ }
+
+ if format == "" {
+ format = "json"
+ }
+
+ file, err := flags.GetString("file")
+ if err != nil {
+ return err
+ }
+
+ verbose, err := flags.GetBool("verbose")
+ if err != nil {
+ return err
+ }
+
+ affected, err := ExecuteDescribeAffected(cliConfig, ref, sha, verbose)
+ if err != nil {
+ return err
+ }
+
+ u.PrintInfoVerbose(verbose && file == "", fmt.Sprintf("\nAffected components and stacks: \n"))
+
+ err = printOrWriteToFile(format, file, affected)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// ExecuteDescribeAffected processes stack configs and returns a list of the affected Atmos components and stacks given two Git commits
+func ExecuteDescribeAffected(
+ cliConfig cfg.CliConfiguration,
+ ref string,
+ sha string,
+ verbose bool,
+) ([]cfg.Affected, error) {
+
+ localRepo, err := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{
+ DetectDotGit: true,
+ EnableDotGitCommonDir: false,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ repoIsNotGitRepoError := errors.New("the current repo is not a Git repository. Check that it was initialized and has '.git' folder")
+
+ // Get the Git config of the current remoteRepo
+ localRepoConfig, err := localRepo.Config()
+ if err != nil {
+ return nil, err
+ }
+
+ keys := []string{}
+ for k := range localRepoConfig.Remotes {
+ keys = append(keys, k)
+ }
+
+ if len(keys) == 0 {
+ return nil, repoIsNotGitRepoError
+ }
+
+ // Get the origin URL of the current remoteRepo
+ remoteUrls := localRepoConfig.Remotes[keys[0]].URLs
+ if len(remoteUrls) == 0 {
+ return nil, repoIsNotGitRepoError
+ }
+
+ repoUrl := remoteUrls[0]
+ if repoUrl == "" {
+ return nil, repoIsNotGitRepoError
+ }
+
+ localRepoHead, err := localRepo.Head()
+ if err != nil {
+ return nil, err
+ }
+
+ // Clone the remote repo
+ // https://git-scm.com/book/en/v2/Git-Internals-Git-References
+ // https://git-scm.com/docs/git-show-ref
+ // https://github.com/go-git/go-git/tree/master/_examples
+ // https://stackoverflow.com/questions/56810719/how-to-checkout-a-specific-sha-in-a-git-repo-using-golang
+ // https://golang.hotexamples.com/examples/gopkg.in.src-d.go-git.v4.plumbing/-/ReferenceName/golang-referencename-function-examples.html
+ // https://stackoverflow.com/questions/58905690/how-to-identify-which-files-have-changed-between-git-commits
+ // https://github.com/src-d/go-git/issues/604
+
+ // Create a temp dir to clone the remote repo to
+ tempDir, err := os.MkdirTemp("", strconv.FormatInt(time.Now().Unix(), 10))
+ if err != nil {
+ return nil, err
+ }
+
+ defer removeTempDir(tempDir)
+
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("\nCloning repo '%s' into the temp dir '%s'", repoUrl, tempDir))
+
+ cloneOptions := git.CloneOptions{
+ URL: repoUrl,
+ NoCheckout: false,
+ SingleBranch: false,
+ }
+
+ // If `ref` flag is not provided, it will clone the HEAD of the default branch
+ if ref != "" {
+ cloneOptions.ReferenceName = plumbing.ReferenceName(ref)
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecking out Git ref '%s' ...\n", ref))
+ } else {
+ u.PrintInfoVerbose(verbose, "\nChecking out the HEAD of the default branch ...\n")
+ }
+
+ if verbose {
+ cloneOptions.Progress = os.Stdout
+ }
+
+ remoteRepo, err := git.PlainClone(tempDir, false, &cloneOptions)
+ if err != nil {
+ return nil, err
+ }
+
+ remoteRepoHead, err := remoteRepo.Head()
+ if err != nil {
+ return nil, err
+ }
+
+ if ref != "" {
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out Git ref '%s'\n", ref))
+ } else {
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out Git ref '%s'\n", remoteRepoHead.Name()))
+ }
+
+ // Check if a commit SHA was provided and checkout the repo at that commit SHA
+ if sha != "" {
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecking out commit SHA '%s' ...\n", sha))
+
+ w, err := remoteRepo.Worktree()
+ if err != nil {
+ return nil, err
+ }
+
+ checkoutOptions := git.CheckoutOptions{
+ Hash: plumbing.NewHash(sha),
+ Create: false,
+ Force: true,
+ Keep: false,
+ }
+
+ err = w.Checkout(&checkoutOptions)
+ if err != nil {
+ return nil, err
+ }
+
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out commit SHA '%s'\n", sha))
+ }
+
+ currentStacks, err := ExecuteDescribeStacks(cliConfig, "", nil, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // Update paths to point to the temp dir
+ cliConfig.StacksBaseAbsolutePath = path.Join(tempDir, cliConfig.BasePath, cliConfig.Stacks.BasePath)
+ cliConfig.TerraformDirAbsolutePath = path.Join(tempDir, cliConfig.BasePath, cliConfig.Components.Terraform.BasePath)
+ cliConfig.HelmfileDirAbsolutePath = path.Join(tempDir, cliConfig.BasePath, cliConfig.Components.Helmfile.BasePath)
+
+ cliConfig.StackConfigFilesAbsolutePaths, err = u.JoinAbsolutePathWithPaths(
+ path.Join(tempDir, cliConfig.BasePath, cliConfig.Stacks.BasePath),
+ cliConfig.StackConfigFilesRelativePaths,
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ remoteStacks, err := ExecuteDescribeStacks(cliConfig, "", nil, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ if verbose {
+ u.PrintInfo(fmt.Sprintf("Current working repo HEAD: %s", localRepoHead))
+ u.PrintInfo(fmt.Sprintf("Remote repo HEAD: %s", remoteRepoHead))
+ }
+
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("\nGetting current working repo commit object..."))
+
+ localCommit, err := localRepo.CommitObject(localRepoHead.Hash())
+ if err != nil {
+ return nil, err
+ }
+
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("Got current working repo commit object"))
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("Getting current working repo commit tree..."))
+
+ localTree, err := localCommit.Tree()
+ if err != nil {
+ return nil, err
+ }
+
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("Got current working repo commit tree"))
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("Getting remote repo commit object..."))
+
+ remoteCommit, err := remoteRepo.CommitObject(remoteRepoHead.Hash())
+ if err != nil {
+ return nil, err
+ }
+
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("Got remote repo commit object"))
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("Getting remote repo commit tree..."))
+
+ remoteTree, err := remoteCommit.Tree()
+ if err != nil {
+ return nil, err
+ }
+
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("Got remote repo commit tree"))
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("Finding diff between the current working branch and remote branch ..."))
+
+ // Find a slice of Patch objects with all the changes between the current working and remote trees
+ patch, err := localTree.Patch(remoteTree)
+ if err != nil {
+ return nil, err
+ }
+
+ u.PrintInfoVerbose(verbose, fmt.Sprintf("Found diff between the current working branch and remote branch"))
+ u.PrintInfoVerbose(verbose, "\nChanged files:")
+
+ var changedFiles []string
+ for _, fileStat := range patch.Stats() {
+ u.PrintMessageVerbose(verbose && fileStat.Name != "", fileStat.Name)
+ changedFiles = append(changedFiles, fileStat.Name)
+ }
+
+ affected := findAffected(currentStacks, remoteStacks, cliConfig, changedFiles)
+ return affected, nil
+}
+
+// findAffected returns a list of all affected components in all stacks
+func findAffected(
+ currentStacks map[string]any,
+ remoteStacks map[string]any,
+ cliConfig cfg.CliConfiguration,
+ changedFiles []string,
+) []cfg.Affected {
+
+ res := []cfg.Affected{}
+
+ for stackName, stackSection := range currentStacks {
+ if stackSectionMap, ok := stackSection.(map[string]any); ok {
+ if componentsSection, ok := stackSectionMap["components"].(map[string]any); ok {
+ if terraformSection, ok := componentsSection["terraform"].(map[string]any); ok {
+ for componentName, compSection := range terraformSection {
+ if componentSection, ok := compSection.(map[string]any); ok {
+ if metadataSection, ok := componentSection["metadata"].(map[any]any); ok {
+ // Skip abstract components
+ if metadataType, ok := metadataSection["type"].(string); ok {
+ if metadataType == "abstract" {
+ continue
+ }
+ }
+ // Check `metadata` section
+ if !isEqual(remoteStacks, stackName, "terraform", componentName, metadataSection, "metadata") {
+ affected := cfg.Affected{
+ ComponentType: "terraform",
+ Component: componentName,
+ Stack: stackName,
+ Affected: "stack.metadata",
+ }
+ res = append(res, affected)
+ continue
+ }
+ }
+ // Check if any files in the component's folder have changed
+ if component, ok := componentSection["component"].(string); ok && component != "" {
+ if isComponentFolderChanged(component, "terraform", cliConfig, changedFiles) {
+ affected := cfg.Affected{
+ ComponentType: "terraform",
+ Component: componentName,
+ Stack: stackName,
+ Affected: "component",
+ }
+ res = append(res, affected)
+ continue
+ }
+ }
+ // Check `vars` section
+ if varSection, ok := componentSection["vars"].(map[any]any); ok {
+ if !isEqual(remoteStacks, stackName, "terraform", componentName, varSection, "vars") {
+ affected := cfg.Affected{
+ ComponentType: "terraform",
+ Component: componentName,
+ Stack: stackName,
+ Affected: "stack.vars",
+ }
+ res = append(res, affected)
+ continue
+ }
+ }
+ // Check `env` section
+ if envSection, ok := componentSection["env"].(map[any]any); ok {
+ if !isEqual(remoteStacks, stackName, "terraform", componentName, envSection, "env") {
+ affected := cfg.Affected{
+ ComponentType: "terraform",
+ Component: componentName,
+ Stack: stackName,
+ Affected: "stack.env",
+ }
+ res = append(res, affected)
+ continue
+ }
+ }
+ // Check `settings` section
+ if settingsSection, ok := componentSection["settings"].(map[any]any); ok {
+ if !isEqual(remoteStacks, stackName, "terraform", componentName, settingsSection, "settings") {
+ affected := cfg.Affected{
+ ComponentType: "terraform",
+ Component: componentName,
+ Stack: stackName,
+ Affected: "stack.settings",
+ }
+ res = append(res, affected)
+ continue
+ }
+ }
+ }
+ }
+ }
+ if helmfileSection, ok := componentsSection["helmfile"].(map[string]any); ok {
+ for componentName, compSection := range helmfileSection {
+ if componentSection, ok := compSection.(map[string]any); ok {
+ if metadataSection, ok := componentSection["metadata"].(map[any]any); ok {
+ // Skip abstract components
+ if metadataType, ok := metadataSection["type"].(string); ok {
+ if metadataType == "abstract" {
+ continue
+ }
+ }
+ // Check `metadata` section
+ if !isEqual(remoteStacks, stackName, "helmfile", componentName, metadataSection, "metadata") {
+ affected := cfg.Affected{
+ ComponentType: "helmfile",
+ Component: componentName,
+ Stack: stackName,
+ Affected: "stack.metadata",
+ }
+ res = append(res, affected)
+ continue
+ }
+ }
+ // Check if any files in the component's folder have changed
+ if component, ok := componentSection["component"].(string); ok && component != "" {
+ if isComponentFolderChanged(component, "helmfile", cliConfig, changedFiles) {
+ affected := cfg.Affected{
+ ComponentType: "helmfile",
+ Component: componentName,
+ Stack: stackName,
+ Affected: "component",
+ }
+ res = append(res, affected)
+ continue
+ }
+ }
+ // Check `vars` section
+ if varSection, ok := componentSection["vars"].(map[any]any); ok {
+ if !isEqual(remoteStacks, stackName, "helmfile", componentName, varSection, "vars") {
+ affected := cfg.Affected{
+ ComponentType: "helmfile",
+ Component: componentName,
+ Stack: stackName,
+ Affected: "stack.vars",
+ }
+ res = append(res, affected)
+ continue
+ }
+ }
+ // Check `env` section
+ if envSection, ok := componentSection["env"].(map[any]any); ok {
+ if !isEqual(remoteStacks, stackName, "helmfile", componentName, envSection, "env") {
+ affected := cfg.Affected{
+ ComponentType: "helmfile",
+ Component: componentName,
+ Stack: stackName,
+ Affected: "stack.env",
+ }
+ res = append(res, affected)
+ continue
+ }
+ }
+ // Check `settings` section
+ if settingsSection, ok := componentSection["settings"].(map[any]any); ok {
+ if !isEqual(remoteStacks, stackName, "helmfile", componentName, settingsSection, "settings") {
+ affected := cfg.Affected{
+ ComponentType: "helmfile",
+ Component: componentName,
+ Stack: stackName,
+ Affected: "stack.settings",
+ }
+ res = append(res, affected)
+ continue
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return res
+}
+
+// isEqual compares a section of a component from the remote stacks with a section of a local component
+func isEqual(
+ remoteStacks map[string]any,
+ localStackName string,
+ componentType string,
+ localComponentName string,
+ localSection map[any]any,
+ sectionName string,
+) bool {
+
+ if remoteStackSection, ok := remoteStacks[localStackName].(map[string]any); ok {
+ if remoteComponentsSection, ok := remoteStackSection["components"].(map[string]any); ok {
+ if remoteComponentTypeSection, ok := remoteComponentsSection[componentType].(map[string]any); ok {
+ if remoteComponentSection, ok := remoteComponentTypeSection[localComponentName].(map[string]any); ok {
+ if remoteSection, ok := remoteComponentSection[sectionName].(map[any]any); ok {
+ if reflect.DeepEqual(localSection, remoteSection) {
+ return true
+ }
+ }
+ }
+ }
+ }
+ }
+ return false
+}
+
+// isComponentFolderChanged checks if a component folder changed (has changed files in it)
+func isComponentFolderChanged(
+ component string,
+ componentType string,
+ cliConfig cfg.CliConfiguration,
+ changedFiles []string,
+) bool {
+
+ var pathPrefix string
+
+ switch componentType {
+ case "terraform":
+ pathPrefix = path.Join(cliConfig.BasePath, cliConfig.Components.Terraform.BasePath, component)
+ case "helmfile":
+ pathPrefix = path.Join(cliConfig.BasePath, cliConfig.Components.Helmfile.BasePath, component)
+ }
+
+ if u.SliceOfPathsContainsPath(changedFiles, pathPrefix) {
+ return true
+ }
+ return false
+}
diff --git a/internal/exec/describe_component.go b/internal/exec/describe_component.go
index cc436288b..c30f0ab2f 100644
--- a/internal/exec/describe_component.go
+++ b/internal/exec/describe_component.go
@@ -60,5 +60,14 @@ func ExecuteDescribeComponent(component string, stack string) (map[string]any, e
}
}
+ // Add Atmos component and stack
+ configAndStacksInfo.ComponentSection["atmos_component"] = configAndStacksInfo.ComponentFromArg
+ configAndStacksInfo.ComponentSection["atmos_stack"] = configAndStacksInfo.StackFromArg
+
+ // If the command-line component does not inherit anything, then the Terraform/Helmfile component is the same as the provided one
+ if comp, ok := configAndStacksInfo.ComponentSection["component"].(string); !ok || comp == "" {
+ configAndStacksInfo.ComponentSection["component"] = configAndStacksInfo.ComponentFromArg
+ }
+
return configAndStacksInfo.ComponentSection, nil
}
diff --git a/internal/exec/describe_stacks.go b/internal/exec/describe_stacks.go
index 78d611d9b..24e10bd44 100644
--- a/internal/exec/describe_stacks.go
+++ b/internal/exec/describe_stacks.go
@@ -34,9 +34,11 @@ func ExecuteDescribeStacksCmd(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
+
if format != "" && format != "yaml" && format != "json" {
return fmt.Errorf("invalid '--format' flag '%s'. Valid values are 'yaml' (default) and 'json'", format)
}
+
if format == "" {
format = "yaml"
}
@@ -50,6 +52,7 @@ func ExecuteDescribeStacksCmd(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
+
var components []string
if componentsCsv != "" {
components = strings.Split(componentsCsv, ",")
@@ -59,6 +62,7 @@ func ExecuteDescribeStacksCmd(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
+
var componentTypes []string
if componentTypesCsv != "" {
componentTypes = strings.Split(componentTypesCsv, ",")
@@ -73,11 +77,33 @@ func ExecuteDescribeStacksCmd(cmd *cobra.Command, args []string) error {
sections = strings.Split(sectionsCsv, ",")
}
- stacksMap, err := FindStacksMap(cliConfig)
+ finalStacksMap, err := ExecuteDescribeStacks(cliConfig, filterByStack, components, componentTypes, sections)
if err != nil {
return err
}
+ err = printOrWriteToFile(format, file, finalStacksMap)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// ExecuteDescribeStacks processes stack configs and returns the final map of stacks and components
+func ExecuteDescribeStacks(
+ cliConfig cfg.CliConfiguration,
+ filterByStack string,
+ components []string,
+ componentTypes []string,
+ sections []string,
+) (map[string]any, error) {
+
+ stacksMap, err := FindStacksMap(cliConfig)
+ if err != nil {
+ return nil, err
+ }
+
finalStacksMap := make(map[string]any)
var varsSection map[any]any
var stackName string
@@ -93,13 +119,13 @@ func ExecuteDescribeStacksCmd(cmd *cobra.Command, args []string) error {
for componentName, compSection := range terraformSection {
componentSection, ok := compSection.(map[string]any)
if !ok {
- return fmt.Errorf("invalid 'components.terraform.%s' section in the file '%s'", componentName, stackFileName)
+ return nil, fmt.Errorf("invalid 'components.terraform.%s' section in the file '%s'", componentName, stackFileName)
}
// Find all derived components of the provided components and include them in the output
derivedComponents, err := s.FindComponentsDerivedFromBaseComponents(stackFileName, terraformSection, components)
if err != nil {
- return err
+ return nil, err
}
// Component vars
@@ -107,7 +133,7 @@ func ExecuteDescribeStacksCmd(cmd *cobra.Command, args []string) error {
context := cfg.GetContextFromVars(varsSection)
stackName, err = cfg.GetContextPrefix(stackFileName, context, cliConfig.Stacks.NamePattern, stackFileName)
if err != nil {
- return err
+ return nil, err
}
}
@@ -149,13 +175,13 @@ func ExecuteDescribeStacksCmd(cmd *cobra.Command, args []string) error {
for componentName, compSection := range helmfileSection {
componentSection, ok := compSection.(map[string]any)
if !ok {
- return fmt.Errorf("invalid 'components.helmfile.%s' section in the file '%s'", componentName, stackFileName)
+ return nil, fmt.Errorf("invalid 'components.helmfile.%s' section in the file '%s'", componentName, stackFileName)
}
// Find all derived components of the provided components and include them in the output
derivedComponents, err := s.FindComponentsDerivedFromBaseComponents(stackFileName, helmfileSection, components)
if err != nil {
- return err
+ return nil, err
}
// Component vars
@@ -163,7 +189,7 @@ func ExecuteDescribeStacksCmd(cmd *cobra.Command, args []string) error {
context := cfg.GetContextFromVars(varsSection)
stackName, err = cfg.GetContextPrefix(stackFileName, context, cliConfig.Stacks.NamePattern, stackFileName)
if err != nil {
- return err
+ return nil, err
}
}
@@ -209,31 +235,5 @@ func ExecuteDescribeStacksCmd(cmd *cobra.Command, args []string) error {
}
}
- if format == "yaml" {
- if file == "" {
- err = u.PrintAsYAML(finalStacksMap)
- if err != nil {
- return err
- }
- } else {
- err = u.WriteToFileAsYAML(file, finalStacksMap, 0644)
- if err != nil {
- return err
- }
- }
- } else if format == "json" {
- if file == "" {
- err = u.PrintAsJSON(finalStacksMap)
- if err != nil {
- return err
- }
- } else {
- err = u.WriteToFileAsJSON(file, finalStacksMap, 0644)
- if err != nil {
- return err
- }
- }
- }
-
- return nil
+ return finalStacksMap, nil
}
diff --git a/internal/exec/utils.go b/internal/exec/utils.go
index ddb99367b..cb58a9c23 100644
--- a/internal/exec/utils.go
+++ b/internal/exec/utils.go
@@ -3,6 +3,7 @@ package exec
import (
"errors"
"fmt"
+ "os"
"strings"
cfg "github.com/cloudposse/atmos/pkg/config"
@@ -674,3 +675,47 @@ func generateComponentBackendConfig(backendType string, backendConfig map[any]an
},
}
}
+
+// printOrWriteToFile takes the output format (`yaml` or `json`) and a file name,
+// and prints the data to the console or to a file (if file is specified)
+func printOrWriteToFile(format string, file string, data any) error {
+ switch format {
+ case "yaml":
+ if file == "" {
+ err := u.PrintAsYAML(data)
+ if err != nil {
+ return err
+ }
+ } else {
+ err := u.WriteToFileAsYAML(file, data, 0644)
+ if err != nil {
+ return err
+ }
+ }
+
+ case "json":
+ if file == "" {
+ err := u.PrintAsJSON(data)
+ if err != nil {
+ return err
+ }
+ } else {
+ err := u.WriteToFileAsJSON(file, data, 0644)
+ if err != nil {
+ return err
+ }
+ }
+
+ default:
+ return fmt.Errorf("invalid 'format': %s", format)
+ }
+
+ return nil
+}
+
+func removeTempDir(path string) {
+ err := os.RemoveAll(path)
+ if err != nil {
+ u.PrintError(err)
+ }
+}
diff --git a/internal/exec/vendor_utils.go b/internal/exec/vendor_utils.go
index 6cc4b8984..a1625a47f 100644
--- a/internal/exec/vendor_utils.go
+++ b/internal/exec/vendor_utils.go
@@ -190,12 +190,7 @@ func ExecuteComponentVendorCommandInternal(
return err
}
- defer func(path string) {
- err := os.RemoveAll(path)
- if err != nil {
- u.PrintError(err)
- }
- }(tempDir)
+ defer removeTempDir(tempDir)
// Download the source into the temp folder
client := &getter.Client{
diff --git a/pkg/config/schema.go b/pkg/config/schema.go
index d3e1c088c..47be27bfa 100644
--- a/pkg/config/schema.go
+++ b/pkg/config/schema.go
@@ -327,3 +327,12 @@ type ValidationItem struct {
}
type Validation map[string]ValidationItem
+
+// Affected Atmos components and stacks given two Git commits
+
+type Affected struct {
+ Stack string `yaml:"stack" json:"stack" mapstructure:"stack"`
+ ComponentType string `yaml:"component_type" json:"component_type" mapstructure:"component_type"`
+ Component string `yaml:"component" json:"component" mapstructure:"component"`
+ Affected string `yaml:"affected" json:"affected" mapstructure:"affected"`
+}
diff --git a/pkg/describe/describe_affected_test.go b/pkg/describe/describe_affected_test.go
new file mode 100644
index 000000000..09200fbde
--- /dev/null
+++ b/pkg/describe/describe_affected_test.go
@@ -0,0 +1,35 @@
+package describe
+
+import (
+ "fmt"
+ e "github.com/cloudposse/atmos/internal/exec"
+ cfg "github.com/cloudposse/atmos/pkg/config"
+ "github.com/stretchr/testify/assert"
+ "gopkg.in/yaml.v2"
+ "testing"
+)
+
+func TestDescribeAffected(t *testing.T) {
+ configAndStacksInfo := cfg.ConfigAndStacksInfo{}
+
+ cliConfig, err := cfg.InitCliConfig(configAndStacksInfo, true)
+ assert.Nil(t, err)
+
+ // We are using `atmos.yaml` from this dir. This `atmos.yaml` has set base_path: "../../examples/complete",
+ // which will be wrong for the remote repo which is cloned into a temp dir.
+ // Set the correct base path for the cloned remote repo
+ cliConfig.BasePath = "./examples/complete"
+
+ // Git reference and commit SHA
+ // Refer to https://git-scm.com/book/en/v2/Git-Internals-Git-References for more details
+ ref := "refs/heads/master"
+ sha := ""
+
+ affected, err := e.ExecuteDescribeAffected(cliConfig, ref, sha, true)
+ assert.Nil(t, err)
+
+ affectedYaml, err := yaml.Marshal(affected)
+ assert.Nil(t, err)
+
+ t.Log(fmt.Sprintf("\nAffected components and stacks:\n%v", string(affectedYaml)))
+}
diff --git a/pkg/describe/terraform_describe_component_test.go b/pkg/describe/describe_component_test.go
similarity index 100%
rename from pkg/describe/terraform_describe_component_test.go
rename to pkg/describe/describe_component_test.go
diff --git a/pkg/utils/file_utils.go b/pkg/utils/file_utils.go
index c3a942c94..7458819da 100644
--- a/pkg/utils/file_utils.go
+++ b/pkg/utils/file_utils.go
@@ -121,3 +121,14 @@ func EnsureDir(fileName string) error {
}
return nil
}
+
+// SliceOfPathsContainsPath checks if a slice of file paths contains a path
+func SliceOfPathsContainsPath(paths []string, checkPath string) bool {
+ for _, v := range paths {
+ dir := path.Dir(v)
+ if dir == checkPath {
+ return true
+ }
+ }
+ return false
+}
diff --git a/website/.nvmrc b/website/.nvmrc
index 2a4e4ab81..b460d6f2d 100644
--- a/website/.nvmrc
+++ b/website/.nvmrc
@@ -1 +1 @@
-16.17.0
+18.12.1
diff --git a/website/docs/cli/commands/describe/describe-affected.md b/website/docs/cli/commands/describe/describe-affected.md
new file mode 100644
index 000000000..f9c00930a
--- /dev/null
+++ b/website/docs/cli/commands/describe/describe-affected.md
@@ -0,0 +1,177 @@
+---
+title: atmos describe affected
+sidebar_label: affected
+sidebar_class_name: command
+id: affected
+description: This command produces a list of the affected Atmos components and stacks given two Git commits.
+---
+
+:::note Purpose
+Use this command to show a list of the affected Atmos components and stacks given two Git commits.
+:::
+
+## Description
+
+The command uses two different Git commits to produce a list of affected Atmos components and stacks.
+
+For the first commit, the command assumes that the current repo root is a Git checkout. An error will be thrown if the current repo is not a Git
+repository (`.git` folder does not exist or is configured incorrectly).
+
+The second commit is specified on the command line by using
+the `--ref` ([Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References)) or `--sha` (commit SHA) flags.
+
+Either `--ref` or `--sha` should be used. If both flags are provided at the same time, the command will first clone the remote branch pointed to by
+the `--ref` flag and then checkout the Git commit pointed to by the `--sha` flag (`--sha` flag overrides `--ref` flag).
+
+If the flags are not provided, the `ref` will be set automatically to the reference to the default branch (e.g. `main`) and the commit SHA will point
+to the `HEAD` of the branch.
+
+The command works by:
+
+- Cloning the branch (`--ref`) or checking out the commit (`--sha`) of the remote target branch
+- Deep merging all stack configurations for both the current working branch and the target branch
+- Looking for changes in the component directories
+- Comparing each section of the stack configuration looking for differences
+- Output a JSON or YAML document consisting of a list of affected components and stacks and what caused it to be affected
+
+Since Atmos first checks the component folders for changes, if it finds any affected files, it will mark all related components and stacks as
+affected. Atmos will then skip evaluating those stacks for differences since we already know that they are affected.
+
+
+
+```shell
+> atmos describe affected --verbose=true
+
+Cloning repo 'https://github.com/cloudposse/atmos' into the temp dir '/var/folders/g5/lbvzy_ld2hx4mgrgyp19bvb00000gn/T/16710736261366892599'
+
+Checking out the HEAD of the default branch ...
+
+Enumerating objects: 4215, done.
+Counting objects: 100% (1157/1157), done.
+Compressing objects: 100% (576/576), done.
+Total 4215 (delta 658), reused 911 (delta 511), pack-reused 3058
+
+Checked out Git ref 'refs/heads/master'
+
+Current working repo HEAD: 7d37c1e890514479fae404d13841a2754be70cbf refs/heads/describe-affected
+Remote repo HEAD: 40210e8d365d3d88ac13c0778c0867b679bbba69 refs/heads/master
+
+Changed files:
+
+examples/complete/components/terraform/infra/vpc/main.tf
+internal/exec/describe_affected.go
+website/docs/cli/commands/describe/describe-affected.md
+
+Affected components and stacks:
+
+[
+ {
+ "stack": "tenant1-ue2-dev",
+ "component_type": "terraform",
+ "component": "infra/vpc",
+ "affected": "component"
+ },
+ {
+ "stack": "tenant1-ue2-prod",
+ "component_type": "terraform",
+ "component": "infra/vpc",
+ "affected": "component"
+ },
+ {
+ "stack": "tenant1-ue2-staging",
+ "component_type": "terraform",
+ "component": "infra/vpc",
+ "affected": "component"
+ }
+]
+```
+
+## Usage
+
+```shell
+atmos describe affected [options]
+```
+
+
+
+:::tip
+Run `atmos describe affected --help` to see all the available options
+:::
+
+## Examples
+
+```shell
+atmos describe affected
+atmos describe affected --verbose=true
+atmos describe affected --ref refs/heads/main
+atmos describe affected --ref refs/heads/my-new-branch --verbose=true
+atmos describe affected --ref refs/heads/main --format json
+atmos describe affected --ref refs/tags/v1.16.0 --file affected.yaml --format yaml
+atmos describe affected --sha 3a5eafeab90426bd82bf5899896b28cc0bab3073 --file affected.json
+atmos describe affected --sha 3a5eafeab90426bd82bf5899896b28cc0bab3073
+```
+
+## Flags
+
+| Flag | Description | Required |
+|:------------|:------------------------------------------------------------------------------------------------------------------------------|:---------|
+| `--ref` | [Git Reference](https://git-scm.com/book/en/v2/Git-Internals-Git-References) with which to compare the current working branch | no |
+| `--sha` | Git commit SHA with which to compare the current working branch | no |
+| `--file` | If specified, write the result to the file | no |
+| `--format` | Specify the output format: `json` or `yaml` (`json` is default) | no |
+| `--verbose` | Print more detailed output when cloning and checking out the Git repository and processing the result | no |
+
+## Output
+
+The command outputs a list of objects (in JSON or YAML format).
+
+Each object has the following schema:
+
+```json
+{
+ "stack": "....",
+ "component_type": "....",
+ "component": "....",
+ "affected": "....."
+}
+```
+
+where:
+
+- `stack` is the affected Atmos stack
+- `component` is the affected Atmos component in the stack
+- `component_type` is the type of the component (`terraform` or `helmfile`)
+- `affected` shows what was changed for the component. The possible values are:
+
+ - `stack.vars` - the `vars` component section in the stack config has been modified
+ - `stack.env` - the `env` component section in the stack config has been modified
+ - `stack.settings` - the `settings` component section in the stack config has been modified
+ - `stack.metadata` - the `metadata` component section in the stack config has been modified
+ - `component` - the Terraform or Helmfile component that the Atmos component provisions has been changed
+
+
+
+For example:
+
+```json
+[
+ {
+ "stack": "tenant2-ue2-staging",
+ "component_type": "terraform",
+ "component": "infra/vpc",
+ "affected": "component"
+ },
+ {
+ "stack": "tenant1-ue2-prod",
+ "component_type": "terraform",
+ "component": "test/test-component-override-3",
+ "affected": "stack.env"
+ },
+ {
+ "stack": "tenant1-ue2-dev",
+ "component_type": "terraform",
+ "component": "test/test-component-override-3",
+ "affected": "stack.vars"
+ }
+]
+```