From 1e3bcf99437b2c2c45a8bc2cc9f5d75eab7a905d Mon Sep 17 00:00:00 2001 From: aknysh Date: Tue, 13 Dec 2022 12:03:35 -0500 Subject: [PATCH 01/47] Update versions --- examples/complete/Dockerfile | 6 ++-- go.mod | 22 +++++++-------- go.sum | 54 +++++++++++++++++++----------------- 3 files changed, 42 insertions(+), 40 deletions(-) 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..3739b83d4 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,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 +21,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 ( @@ -38,9 +38,9 @@ require ( 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/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 @@ -86,8 +86,8 @@ require ( github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // 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 @@ -106,18 +106,18 @@ 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/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/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index b0f87963b..a2601c4a7 100644 --- a/go.sum +++ b/go.sum @@ -73,7 +73,7 @@ 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/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= @@ -106,8 +106,8 @@ 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/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= @@ -130,16 +130,16 @@ 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.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= @@ -177,7 +177,7 @@ 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= @@ -354,7 +354,7 @@ 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.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= @@ -399,8 +399,8 @@ 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/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= @@ -430,13 +430,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,7 +457,7 @@ 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= @@ -627,8 +628,8 @@ 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.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= @@ -742,11 +743,12 @@ golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBc 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-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.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.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 +758,8 @@ 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= @@ -991,8 +993,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= @@ -1040,8 +1042,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= From 56d89d1024d06915e5ed42da6e276a2b0ebe98ad Mon Sep 17 00:00:00 2001 From: aknysh Date: Tue, 13 Dec 2022 12:20:49 -0500 Subject: [PATCH 02/47] Add `atmos describe affected` command --- cmd/describe_affected.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 cmd/describe_affected.go diff --git a/cmd/describe_affected.go b/cmd/describe_affected.go new file mode 100644 index 000000000..eef331076 --- /dev/null +++ b/cmd/describe_affected.go @@ -0,0 +1,31 @@ +package cmd + +import ( + "github.com/spf13/cobra" + + e "github.com/cloudposse/atmos/internal/exec" + u "github.com/cloudposse/atmos/pkg/utils" +) + +// describeAffectedCmd shows the affected (changed) configurations for Atmos stacks and components in the stacks +var describeAffectedCmd = &cobra.Command{ + Use: "affected", + Short: "Execute 'describe affected' command", + Long: `This command shows the affected (changed) configurations for Atmos stacks and components in the stacks: atmos describe stacks [options]`, + FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: true}, + Run: func(cmd *cobra.Command, args []string) { + err := e.ExecuteDescribeStacksCmd(cmd, args) + if err != nil { + u.PrintErrorToStdErrorAndExit(err) + } + }, +} + +func init() { + describeAffectedCmd.DisableFlagParsing = false + + describeAffectedCmd.PersistentFlags().String("file", "", "Write the result to file: atmos describe affected --file=affected.yaml") + describeAffectedCmd.PersistentFlags().String("format", "yaml", "Specify the output format: atmos describe affected --format=json|yaml ('json' is default)") + + describeCmd.AddCommand(describeAffectedCmd) +} From 0394de0b5499795ca25da521dbb7a4cd85ff755b Mon Sep 17 00:00:00 2001 From: aknysh Date: Tue, 13 Dec 2022 12:55:24 -0500 Subject: [PATCH 03/47] Add `atmos describe affected` command --- cmd/describe_affected.go | 14 +- internal/exec/describe_affected.go | 239 ++++++++++++++++++ .../commands/describe/describe-affected.md | 42 +++ 3 files changed, 291 insertions(+), 4 deletions(-) create mode 100644 internal/exec/describe_affected.go create mode 100644 website/docs/cli/commands/describe/describe-affected.md diff --git a/cmd/describe_affected.go b/cmd/describe_affected.go index eef331076..083848e37 100644 --- a/cmd/describe_affected.go +++ b/cmd/describe_affected.go @@ -7,14 +7,14 @@ import ( u "github.com/cloudposse/atmos/pkg/utils" ) -// describeAffectedCmd shows the affected (changed) configurations for Atmos stacks and components in the stacks +// 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 shows the affected (changed) configurations for Atmos stacks and components in the stacks: atmos describe stacks [options]`, + 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.ExecuteDescribeStacksCmd(cmd, args) + err := e.ExecuteDescribeAffectedCmd(cmd, args) if err != nil { u.PrintErrorToStdErrorAndExit(err) } @@ -24,8 +24,14 @@ var describeAffectedCmd = &cobra.Command{ func init() { describeAffectedCmd.DisableFlagParsing = false + describeAffectedCmd.PersistentFlags().String("base", "", "The SHA of a Git commit to compare the current Git checkout to: atmos describe affected --since=origin/main") describeAffectedCmd.PersistentFlags().String("file", "", "Write the result to file: atmos describe affected --file=affected.yaml") - describeAffectedCmd.PersistentFlags().String("format", "yaml", "Specify the output format: atmos describe affected --format=json|yaml ('json' is default)") + describeAffectedCmd.PersistentFlags().String("format", "json", "The output format: atmos describe affected --format=json|yaml ('json' is default)") + + err := describeAffectedCmd.MarkPersistentFlagRequired("base") + if err != nil { + u.PrintErrorToStdErrorAndExit(err) + } describeCmd.AddCommand(describeAffectedCmd) } diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go new file mode 100644 index 000000000..5ef2eb59e --- /dev/null +++ b/internal/exec/describe_affected.go @@ -0,0 +1,239 @@ +package exec + +import ( + "fmt" + "github.com/spf13/cobra" + "strings" + + cfg "github.com/cloudposse/atmos/pkg/config" + s "github.com/cloudposse/atmos/pkg/stack" + u "github.com/cloudposse/atmos/pkg/utils" +) + +// 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 + } + + flags := cmd.Flags() + + filterByStack, err := flags.GetString("stack") + 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 'yaml' (default) and 'json'", format) + } + if format == "" { + format = "yaml" + } + + file, err := flags.GetString("file") + if err != nil { + return err + } + + componentsCsv, err := flags.GetString("components") + if err != nil { + return err + } + var components []string + if componentsCsv != "" { + components = strings.Split(componentsCsv, ",") + } + + componentTypesCsv, err := flags.GetString("component-types") + if err != nil { + return err + } + var componentTypes []string + if componentTypesCsv != "" { + componentTypes = strings.Split(componentTypesCsv, ",") + } + + sectionsCsv, err := flags.GetString("sections") + if err != nil { + return err + } + var sections []string + if sectionsCsv != "" { + sections = strings.Split(sectionsCsv, ",") + } + + stacksMap, err := FindStacksMap(cliConfig) + if err != nil { + return err + } + + finalStacksMap := make(map[string]any) + var varsSection map[any]any + var stackName string + + for stackFileName, stackSection := range stacksMap { + // Delete the stack-wide imports + delete(stackSection.(map[any]any), "imports") + + if componentsSection, ok := stackSection.(map[any]any)["components"].(map[string]any); ok { + + if len(componentTypes) == 0 || u.SliceContainsString(componentTypes, "terraform") { + if terraformSection, ok := componentsSection["terraform"].(map[string]any); ok { + 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) + } + + // 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 + } + + // Component vars + if varsSection, ok = componentSection["vars"].(map[any]any); ok { + context := cfg.GetContextFromVars(varsSection) + stackName, err = cfg.GetContextPrefix(stackFileName, context, cliConfig.Stacks.NamePattern, stackFileName) + if err != nil { + return err + } + } + + if filterByStack != "" && filterByStack != stackFileName && filterByStack != stackName { + continue + } + + if stackName == "" { + stackName = stackFileName + } + + if !u.MapKeyExists(finalStacksMap, stackName) { + finalStacksMap[stackName] = make(map[string]any) + } + + if len(components) == 0 || u.SliceContainsString(components, componentName) || u.SliceContainsString(derivedComponents, componentName) { + if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any), "components") { + finalStacksMap[stackName].(map[string]any)["components"] = make(map[string]any) + } + if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any)["components"].(map[string]any), "terraform") { + finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["terraform"] = make(map[string]any) + } + if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["terraform"].(map[string]any), componentName) { + finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["terraform"].(map[string]any)[componentName] = make(map[string]any) + } + + for sectionName, section := range componentSection { + if len(sections) == 0 || u.SliceContainsString(sections, sectionName) { + finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["terraform"].(map[string]any)[componentName].(map[string]any)[sectionName] = section + } + } + } + } + } + } + + if len(componentTypes) == 0 || u.SliceContainsString(componentTypes, "helmfile") { + if helmfileSection, ok := componentsSection["helmfile"].(map[string]any); ok { + 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) + } + + // 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 + } + + // Component vars + if varsSection, ok = componentSection["vars"].(map[any]any); ok { + context := cfg.GetContextFromVars(varsSection) + stackName, err = cfg.GetContextPrefix(stackFileName, context, cliConfig.Stacks.NamePattern, stackFileName) + if err != nil { + return err + } + } + + if filterByStack != "" && filterByStack != stackFileName && filterByStack != stackName { + continue + } + + if stackName == "" { + stackName = stackFileName + } + + if !u.MapKeyExists(finalStacksMap, stackName) { + finalStacksMap[stackName] = make(map[string]any) + } + + if len(components) == 0 || u.SliceContainsString(components, componentName) || u.SliceContainsString(derivedComponents, componentName) { + if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any), "components") { + finalStacksMap[stackName].(map[string]any)["components"] = make(map[string]any) + } + if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any)["components"].(map[string]any), "helmfile") { + finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["helmfile"] = make(map[string]any) + } + if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["helmfile"].(map[string]any), componentName) { + finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["helmfile"].(map[string]any)[componentName] = make(map[string]any) + } + + for sectionName, section := range componentSection { + if len(sections) == 0 || u.SliceContainsString(sections, sectionName) { + finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["helmfile"].(map[string]any)[componentName].(map[string]any)[sectionName] = section + } + } + } + } + } + } + } + + // Filter out empty stacks (stacks without any components) + if st, ok := finalStacksMap[stackName].(map[string]any); ok { + if len(st) == 0 { + delete(finalStacksMap, stackName) + } + } + } + + 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 +} 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..163f155c6 --- /dev/null +++ b/website/docs/cli/commands/describe/describe-affected.md @@ -0,0 +1,42 @@ +--- +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. +For the first commit, the command assumes that the Atmos root is a Git checkout. +The second commit SHA is specified on the command line. +::: + +## Usage + +```shell +atmos describe affected [options] +``` + +
+ +:::tip +Run `atmos describe affected --help` to see all the available options +::: + +## Examples + +```shell +atmos describe affected --base origin/main +atmos describe affected --base origin/main --format json +atmos describe affected --base origin/main --file affected.json +atmos describe affected --base origin/main --file affected.yaml --format yaml +``` + +## Flags + +| Flag | Description | Required | +|:-----------|:----------------------------------------------------------------|:---------| +| `--base` | The SHA of a Git commit to compare the current Git checkout to | yes | +| `--file` | If specified, write the result to the file | no | +| `--format` | Specify the output format: `json` or `yaml` (`json` is default) | no | From 1e90abc4a356b16fdd4df7080656deec45182fae Mon Sep 17 00:00:00 2001 From: aknysh Date: Tue, 13 Dec 2022 13:19:34 -0500 Subject: [PATCH 04/47] Add `atmos describe affected` command --- cmd/describe_affected.go | 6 +++--- .../docs/cli/commands/describe/describe-affected.md | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/describe_affected.go b/cmd/describe_affected.go index 083848e37..5488c76d3 100644 --- a/cmd/describe_affected.go +++ b/cmd/describe_affected.go @@ -24,11 +24,11 @@ var describeAffectedCmd = &cobra.Command{ func init() { describeAffectedCmd.DisableFlagParsing = false - describeAffectedCmd.PersistentFlags().String("base", "", "The SHA of a Git commit to compare the current Git checkout to: atmos describe affected --since=origin/main") - describeAffectedCmd.PersistentFlags().String("file", "", "Write the result to file: atmos describe affected --file=affected.yaml") + describeAffectedCmd.PersistentFlags().String("target", "", "The SHA of a Git commit to compare the current Git checkout to: atmos describe affected --target origin/main") + describeAffectedCmd.PersistentFlags().String("file", "", "Write the result to file: atmos describe affected --file affected.yaml") describeAffectedCmd.PersistentFlags().String("format", "json", "The output format: atmos describe affected --format=json|yaml ('json' is default)") - err := describeAffectedCmd.MarkPersistentFlagRequired("base") + err := describeAffectedCmd.MarkPersistentFlagRequired("target") if err != nil { u.PrintErrorToStdErrorAndExit(err) } diff --git a/website/docs/cli/commands/describe/describe-affected.md b/website/docs/cli/commands/describe/describe-affected.md index 163f155c6..162d9d8cb 100644 --- a/website/docs/cli/commands/describe/describe-affected.md +++ b/website/docs/cli/commands/describe/describe-affected.md @@ -27,16 +27,16 @@ Run `atmos describe affected --help` to see all the available options ## Examples ```shell -atmos describe affected --base origin/main -atmos describe affected --base origin/main --format json -atmos describe affected --base origin/main --file affected.json -atmos describe affected --base origin/main --file affected.yaml --format yaml +atmos describe affected --target origin/main +atmos describe affected --target origin/main --format json +atmos describe affected --target origin/main --file affected.json +atmos describe affected --target origin/main --file affected.yaml --format yaml ``` ## Flags | Flag | Description | Required | |:-----------|:----------------------------------------------------------------|:---------| -| `--base` | The SHA of a Git commit to compare the current Git checkout to | yes | +| `--target` | The SHA of a Git commit to compare the current Git checkout to | yes | | `--file` | If specified, write the result to the file | no | | `--format` | Specify the output format: `json` or `yaml` (`json` is default) | no | From 15701db4b5c33258be0fd4515c781f4e0fa7416c Mon Sep 17 00:00:00 2001 From: aknysh Date: Tue, 13 Dec 2022 16:16:28 -0500 Subject: [PATCH 05/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 171 +++++----------------------- internal/exec/describe_component.go | 5 + internal/exec/describe_stacks.go | 84 ++++++++------ 3 files changed, 86 insertions(+), 174 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 5ef2eb59e..a863f3c29 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -3,10 +3,8 @@ package exec import ( "fmt" "github.com/spf13/cobra" - "strings" cfg "github.com/cloudposse/atmos/pkg/config" - s "github.com/cloudposse/atmos/pkg/stack" u "github.com/cloudposse/atmos/pkg/utils" ) @@ -25,11 +23,6 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { flags := cmd.Flags() - filterByStack, err := flags.GetString("stack") - if err != nil { - return err - } - format, err := flags.GetString("format") if err != nil { return err @@ -38,7 +31,7 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("invalid '--format' flag '%s'. Valid values are 'yaml' (default) and 'json'", format) } if format == "" { - format = "yaml" + format = "json" } file, err := flags.GetString("file") @@ -46,33 +39,6 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { return err } - componentsCsv, err := flags.GetString("components") - if err != nil { - return err - } - var components []string - if componentsCsv != "" { - components = strings.Split(componentsCsv, ",") - } - - componentTypesCsv, err := flags.GetString("component-types") - if err != nil { - return err - } - var componentTypes []string - if componentTypesCsv != "" { - componentTypes = strings.Split(componentTypesCsv, ",") - } - - sectionsCsv, err := flags.GetString("sections") - if err != nil { - return err - } - var sections []string - if sectionsCsv != "" { - sections = strings.Split(sectionsCsv, ",") - } - stacksMap, err := FindStacksMap(cliConfig) if err != nil { return err @@ -88,124 +54,49 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { if componentsSection, ok := stackSection.(map[any]any)["components"].(map[string]any); ok { - if len(componentTypes) == 0 || u.SliceContainsString(componentTypes, "terraform") { - if terraformSection, ok := componentsSection["terraform"].(map[string]any); ok { - 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) - } - - // 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 - } - - // Component vars - if varsSection, ok = componentSection["vars"].(map[any]any); ok { - context := cfg.GetContextFromVars(varsSection) - stackName, err = cfg.GetContextPrefix(stackFileName, context, cliConfig.Stacks.NamePattern, stackFileName) - if err != nil { - return err - } - } - - if filterByStack != "" && filterByStack != stackFileName && filterByStack != stackName { - continue - } - - if stackName == "" { - stackName = stackFileName - } - - if !u.MapKeyExists(finalStacksMap, stackName) { - finalStacksMap[stackName] = make(map[string]any) - } - - if len(components) == 0 || u.SliceContainsString(components, componentName) || u.SliceContainsString(derivedComponents, componentName) { - if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any), "components") { - finalStacksMap[stackName].(map[string]any)["components"] = make(map[string]any) - } - if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any)["components"].(map[string]any), "terraform") { - finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["terraform"] = make(map[string]any) - } - if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["terraform"].(map[string]any), componentName) { - finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["terraform"].(map[string]any)[componentName] = make(map[string]any) - } - - for sectionName, section := range componentSection { - if len(sections) == 0 || u.SliceContainsString(sections, sectionName) { - finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["terraform"].(map[string]any)[componentName].(map[string]any)[sectionName] = section - } - } - } + if terraformSection, ok := componentsSection["terraform"].(map[string]any); ok { + 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) } - } - } - - if len(componentTypes) == 0 || u.SliceContainsString(componentTypes, "helmfile") { - if helmfileSection, ok := componentsSection["helmfile"].(map[string]any); ok { - 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) - } - // Find all derived components of the provided components and include them in the output - derivedComponents, err := s.FindComponentsDerivedFromBaseComponents(stackFileName, helmfileSection, components) + // Component vars + if varsSection, ok = componentSection["vars"].(map[any]any); ok { + context := cfg.GetContextFromVars(varsSection) + stackName, err = cfg.GetContextPrefix(stackFileName, context, cliConfig.Stacks.NamePattern, stackFileName) if err != nil { return err } + } - // Component vars - if varsSection, ok = componentSection["vars"].(map[any]any); ok { - context := cfg.GetContextFromVars(varsSection) - stackName, err = cfg.GetContextPrefix(stackFileName, context, cliConfig.Stacks.NamePattern, stackFileName) - if err != nil { - return err - } - } - - if filterByStack != "" && filterByStack != stackFileName && filterByStack != stackName { - continue - } - - if stackName == "" { - stackName = stackFileName - } + if stackName == "" { + stackName = stackFileName + } - if !u.MapKeyExists(finalStacksMap, stackName) { - finalStacksMap[stackName] = make(map[string]any) - } + if !u.MapKeyExists(finalStacksMap, stackName) { + finalStacksMap[stackName] = make(map[string]any) + } - if len(components) == 0 || u.SliceContainsString(components, componentName) || u.SliceContainsString(derivedComponents, componentName) { - if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any), "components") { - finalStacksMap[stackName].(map[string]any)["components"] = make(map[string]any) - } - if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any)["components"].(map[string]any), "helmfile") { - finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["helmfile"] = make(map[string]any) - } - if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["helmfile"].(map[string]any), componentName) { - finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["helmfile"].(map[string]any)[componentName] = make(map[string]any) - } - - for sectionName, section := range componentSection { - if len(sections) == 0 || u.SliceContainsString(sections, sectionName) { - finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["helmfile"].(map[string]any)[componentName].(map[string]any)[sectionName] = section - } - } - } + if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any), "components") { + finalStacksMap[stackName].(map[string]any)["components"] = make(map[string]any) + } + if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any)["components"].(map[string]any), "terraform") { + finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["terraform"] = make(map[string]any) + } + if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["terraform"].(map[string]any), componentName) { + finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["terraform"].(map[string]any)[componentName] = make(map[string]any) } + } } } + } - // Filter out empty stacks (stacks without any components) - if st, ok := finalStacksMap[stackName].(map[string]any); ok { - if len(st) == 0 { - delete(finalStacksMap, stackName) - } + // Filter out empty stacks (stacks without any components) + if st, ok := finalStacksMap[stackName].(map[string]any); ok { + if len(st) == 0 { + delete(finalStacksMap, stackName) } } diff --git a/internal/exec/describe_component.go b/internal/exec/describe_component.go index cc436288b..0d384cf47 100644 --- a/internal/exec/describe_component.go +++ b/internal/exec/describe_component.go @@ -60,5 +60,10 @@ func ExecuteDescribeComponent(component string, stack string) (map[string]any, e } } + // Always add component, base component (if any) and stack to the `atmos describe component` command output + configAndStacksInfo.ComponentSection["component"] = configAndStacksInfo.ComponentFromArg + configAndStacksInfo.ComponentSection["base_component"] = configAndStacksInfo.BaseComponent + configAndStacksInfo.ComponentSection["stack"] = configAndStacksInfo.StackFromArg + return configAndStacksInfo.ComponentSection, nil } diff --git a/internal/exec/describe_stacks.go b/internal/exec/describe_stacks.go index 78d611d9b..97223f690 100644 --- a/internal/exec/describe_stacks.go +++ b/internal/exec/describe_stacks.go @@ -73,11 +73,53 @@ 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 } + 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 +} + +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 +135,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 +149,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 +191,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 +205,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 +251,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 } From 02d95a429711d4cbd793ff8dc4a5a09e82568323 Mon Sep 17 00:00:00 2001 From: aknysh Date: Tue, 13 Dec 2022 16:20:43 -0500 Subject: [PATCH 06/47] Add `atmos describe affected` command --- cmd/describe_affected.go | 8 ++++---- .../cli/commands/describe/describe-affected.md | 15 ++++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/cmd/describe_affected.go b/cmd/describe_affected.go index 5488c76d3..f2f63de42 100644 --- a/cmd/describe_affected.go +++ b/cmd/describe_affected.go @@ -24,11 +24,11 @@ var describeAffectedCmd = &cobra.Command{ func init() { describeAffectedCmd.DisableFlagParsing = false - describeAffectedCmd.PersistentFlags().String("target", "", "The SHA of a Git commit to compare the current Git checkout to: atmos describe affected --target origin/main") - describeAffectedCmd.PersistentFlags().String("file", "", "Write the result to file: atmos describe affected --file affected.yaml") - describeAffectedCmd.PersistentFlags().String("format", "json", "The output format: atmos describe affected --format=json|yaml ('json' is default)") + describeAffectedCmd.PersistentFlags().String("base", "", "The SHA of a Git commit to compare the current Git checkout to: atmos describe affected --base origin/main") + describeAffectedCmd.PersistentFlags().String("file", "", "Write the result to file: atmos describe affected --base origin/main --file affected.json") + describeAffectedCmd.PersistentFlags().String("format", "json", "The output format: atmos describe affected --base origin/main --format=json|yaml ('json' is default)") - err := describeAffectedCmd.MarkPersistentFlagRequired("target") + err := describeAffectedCmd.MarkPersistentFlagRequired("base") if err != nil { u.PrintErrorToStdErrorAndExit(err) } diff --git a/website/docs/cli/commands/describe/describe-affected.md b/website/docs/cli/commands/describe/describe-affected.md index 162d9d8cb..d5e8ac37e 100644 --- a/website/docs/cli/commands/describe/describe-affected.md +++ b/website/docs/cli/commands/describe/describe-affected.md @@ -8,8 +8,9 @@ description: This command produces a list of the affected Atmos components and s :::note Purpose Use this command to show a list of the affected Atmos components and stacks given two Git commits. -For the first commit, the command assumes that the Atmos root is a Git checkout. -The second commit SHA is specified on the command line. + +For the first commit, the command assumes that the repo root is a Git checkout. +The second commit SHA is specified on the command line using the `--base` flag. ::: ## Usage @@ -27,16 +28,16 @@ Run `atmos describe affected --help` to see all the available options ## Examples ```shell -atmos describe affected --target origin/main -atmos describe affected --target origin/main --format json -atmos describe affected --target origin/main --file affected.json -atmos describe affected --target origin/main --file affected.yaml --format yaml +atmos describe affected --base origin/main +atmos describe affected --base origin/main --format json +atmos describe affected --base origin/main --file affected.json +atmos describe affected --base origin/main --file affected.yaml --format yaml ``` ## Flags | Flag | Description | Required | |:-----------|:----------------------------------------------------------------|:---------| -| `--target` | The SHA of a Git commit to compare the current Git checkout to | yes | +| `--base` | The SHA of a Git commit to compare the current Git checkout to | yes | | `--file` | If specified, write the result to the file | no | | `--format` | Specify the output format: `json` or `yaml` (`json` is default) | no | From 28e637624098e70d69201e870522a0c16f6420c7 Mon Sep 17 00:00:00 2001 From: aknysh Date: Tue, 13 Dec 2022 16:54:43 -0500 Subject: [PATCH 07/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 77 ++++++++---------------------- internal/exec/describe_stacks.go | 1 + 2 files changed, 21 insertions(+), 57 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index a863f3c29..5ca90a5b3 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -23,6 +23,11 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { flags := cmd.Flags() + base, err := flags.GetString("base") + if err != nil { + return err + } + format, err := flags.GetString("format") if err != nil { return err @@ -39,67 +44,11 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { return err } - stacksMap, err := FindStacksMap(cliConfig) + finalStacksMap, err := ExecuteDescribeAffected(cliConfig, base) if err != nil { return err } - finalStacksMap := make(map[string]any) - var varsSection map[any]any - var stackName string - - for stackFileName, stackSection := range stacksMap { - // Delete the stack-wide imports - delete(stackSection.(map[any]any), "imports") - - if componentsSection, ok := stackSection.(map[any]any)["components"].(map[string]any); ok { - - if terraformSection, ok := componentsSection["terraform"].(map[string]any); ok { - 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) - } - - // Component vars - if varsSection, ok = componentSection["vars"].(map[any]any); ok { - context := cfg.GetContextFromVars(varsSection) - stackName, err = cfg.GetContextPrefix(stackFileName, context, cliConfig.Stacks.NamePattern, stackFileName) - if err != nil { - return err - } - } - - if stackName == "" { - stackName = stackFileName - } - - if !u.MapKeyExists(finalStacksMap, stackName) { - finalStacksMap[stackName] = make(map[string]any) - } - - if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any), "components") { - finalStacksMap[stackName].(map[string]any)["components"] = make(map[string]any) - } - if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any)["components"].(map[string]any), "terraform") { - finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["terraform"] = make(map[string]any) - } - if !u.MapKeyExists(finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["terraform"].(map[string]any), componentName) { - finalStacksMap[stackName].(map[string]any)["components"].(map[string]any)["terraform"].(map[string]any)[componentName] = make(map[string]any) - } - - } - } - } - } - - // Filter out empty stacks (stacks without any components) - if st, ok := finalStacksMap[stackName].(map[string]any); ok { - if len(st) == 0 { - delete(finalStacksMap, stackName) - } - } - if format == "yaml" { if file == "" { err = u.PrintAsYAML(finalStacksMap) @@ -128,3 +77,17 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { 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, + base string, +) (map[string]any, error) { + + finalStacksMap, err := ExecuteDescribeStacks(cliConfig, "", nil, nil, nil) + if err != nil { + return nil, err + } + + return finalStacksMap, nil +} diff --git a/internal/exec/describe_stacks.go b/internal/exec/describe_stacks.go index 97223f690..59e80a0c1 100644 --- a/internal/exec/describe_stacks.go +++ b/internal/exec/describe_stacks.go @@ -107,6 +107,7 @@ func ExecuteDescribeStacksCmd(cmd *cobra.Command, args []string) error { return nil } +// ExecuteDescribeStacks processes stack configs and returns the final map of stacks and components func ExecuteDescribeStacks( cliConfig cfg.CliConfiguration, filterByStack string, From 55f1a82c94edc4a02ef2f4fce9aac0f6ce49251c Mon Sep 17 00:00:00 2001 From: aknysh Date: Tue, 13 Dec 2022 21:32:01 -0500 Subject: [PATCH 08/47] Add `atmos describe affected` command --- cmd/describe_affected.go | 13 +- go.mod | 18 +++ go.sum | 75 +++++++++- internal/exec/describe_affected.go | 136 +++++++++++++++--- .../commands/describe/describe-affected.md | 24 ++-- 5 files changed, 229 insertions(+), 37 deletions(-) diff --git a/cmd/describe_affected.go b/cmd/describe_affected.go index f2f63de42..88d81a2a6 100644 --- a/cmd/describe_affected.go +++ b/cmd/describe_affected.go @@ -24,14 +24,11 @@ var describeAffectedCmd = &cobra.Command{ func init() { describeAffectedCmd.DisableFlagParsing = false - describeAffectedCmd.PersistentFlags().String("base", "", "The SHA of a Git commit to compare the current Git checkout to: atmos describe affected --base origin/main") - describeAffectedCmd.PersistentFlags().String("file", "", "Write the result to file: atmos describe affected --base origin/main --file affected.json") - describeAffectedCmd.PersistentFlags().String("format", "json", "The output format: atmos describe affected --base origin/main --format=json|yaml ('json' is default)") - - err := describeAffectedCmd.MarkPersistentFlagRequired("base") - if err != nil { - u.PrintErrorToStdErrorAndExit(err) - } + 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 --ref refs/heads/my-new-branch --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 --ref refs/heads/main --format=json|yaml ('json' is default)") + describeAffectedCmd.PersistentFlags().Bool("verbose", false, "atmos describe affected --ref refs/heads/main --verbose=true") describeCmd.AddCommand(describeAffectedCmd) } diff --git a/go.mod b/go.mod index 3739b83d4..42691185b 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 @@ -19,6 +20,7 @@ require ( github.com/spf13/cobra v1.6.1 github.com/spf13/viper v1.14.0 github.com/stretchr/testify v1.8.1 + github.com/tcnksm/go-gitconfig v0.1.2 github.com/zclconf/go-cty v1.12.1 gopkg.in/yaml.v2 v2.4.0 mvdan.cc/sh/v3 v3.6.0 @@ -31,7 +33,10 @@ 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 @@ -40,6 +45,7 @@ require ( github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // 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 @@ -49,8 +55,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 +77,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 @@ -81,17 +92,21 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/morikuni/aec v1.0.0 // indirect + github.com/onsi/gomega v1.24.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect 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.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 +114,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,6 +122,7 @@ 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/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 @@ -120,6 +137,7 @@ require ( 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 a2601c4a7..bc1f45e87 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/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,6 +115,7 @@ 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/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= @@ -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= @@ -133,6 +145,7 @@ github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBd 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.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= @@ -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= @@ -182,6 +197,16 @@ github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4 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.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,6 +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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= +github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= 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= @@ -417,6 +454,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= @@ -462,11 +501,15 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD 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= @@ -499,8 +542,12 @@ github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= +github.com/tcnksm/go-gitconfig v0.1.2 h1:iiDhRitByXAEyjgBqsKi9QU4o2TNtv9kPP3RgPgXBPw= +github.com/tcnksm/go-gitconfig v0.1.2/go.mod h1:/8EhP4H7oJZdIPyT+/UIsG87kTzrzM4UsLGSItWYCpE= 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= @@ -512,6 +559,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= @@ -545,8 +593,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= @@ -582,6 +635,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= @@ -621,6 +675,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= @@ -628,6 +683,9 @@ 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-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= @@ -664,6 +722,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= @@ -680,6 +739,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= @@ -726,6 +786,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= @@ -742,11 +803,17 @@ 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.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/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= @@ -758,6 +825,7 @@ 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/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= @@ -820,6 +888,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= @@ -1016,11 +1085,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= diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 5ca90a5b3..3667f104f 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -2,7 +2,14 @@ package exec import ( "fmt" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + "github.com/pkg/errors" "github.com/spf13/cobra" + "github.com/tcnksm/go-gitconfig" + "os" + "strconv" + "time" cfg "github.com/cloudposse/atmos/pkg/config" u "github.com/cloudposse/atmos/pkg/utils" @@ -21,13 +28,23 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { return err } + // Process flags flags := cmd.Flags() - base, err := flags.GetString("base") + ref, err := flags.GetString("ref") if err != nil { return err } + sha, err := flags.GetString("sha") + if err != nil { + return err + } + + if ref == "" && sha == "" { + return fmt.Errorf("invalid flag. Either '--ref' or '--sha' is required. Both can be specified") + } + format, err := flags.GetString("format") if err != nil { return err @@ -44,31 +61,36 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { return err } - finalStacksMap, err := ExecuteDescribeAffected(cliConfig, base) + verbose, err := flags.GetBool("verbose") + if err != nil { + return err + } + + affected, err := ExecuteDescribeAffected(cliConfig, ref, sha, verbose) if err != nil { return err } 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 - } - } + //if file == "" { + // err = u.PrintAsYAML(affected) + // if err != nil { + // return err + // } + //} else { + // err = u.WriteToFileAsYAML(file, affected, 0644) + // if err != nil { + // return err + // } + //} } else if format == "json" { if file == "" { - err = u.PrintAsJSON(finalStacksMap) + err = u.PrintAsJSON(affected) if err != nil { return err } } else { - err = u.WriteToFileAsJSON(file, finalStacksMap, 0644) + err = u.WriteToFileAsJSON(file, affected, 0644) if err != nil { return err } @@ -81,13 +103,91 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { // ExecuteDescribeAffected processes stack configs and returns a list of the affected Atmos components and stacks given two Git commits func ExecuteDescribeAffected( cliConfig cfg.CliConfiguration, - base string, + ref string, + sha string, + verbose bool, ) (map[string]any, error) { - finalStacksMap, err := ExecuteDescribeStacks(cliConfig, "", nil, nil, nil) + // Get the origin URL of the current branch + repoUrl, err := gitconfig.OriginURL() + if err != nil { + return nil, err + } + if repoUrl == "" { + return nil, errors.New("the current repo is not a Git repository. Check that it was initialized and has '.git' folder") + } + + // 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 func(path string) { + err := os.RemoveAll(path) + if err != nil { + u.PrintError(err) + } + }(tempDir) + + // Clone the remote repo + // https://git-scm.com/book/en/v2/Git-Internals-Git-References + // 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 + + if verbose { + u.PrintInfo(fmt.Sprintf("\nCloning repo '%s' into a temp dir", repoUrl)) + } + + cloneOptions := git.CloneOptions{ + URL: repoUrl, + NoCheckout: false, + SingleBranch: false, + } + + if ref != "" { + cloneOptions.ReferenceName = plumbing.ReferenceName(ref) + if verbose { + u.PrintInfo(fmt.Sprintf("Git ref: %s", ref)) + } + } + if verbose { + cloneOptions.Progress = os.Stdout + } + + repo, err := git.PlainClone(tempDir, false, &cloneOptions) + if err != nil { + return nil, err + } + + // Check if a commit SHA was provided and checkout the repo at that commit SHA + if sha != "" { + if verbose { + u.PrintInfo(fmt.Sprintf("\nChecking out SHA: %s\n", sha)) + } + + w, err := repo.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 + } + } + + affected, err := ExecuteDescribeStacks(cliConfig, "", nil, nil, nil) if err != nil { return nil, err } - return finalStacksMap, nil + return affected, nil } diff --git a/website/docs/cli/commands/describe/describe-affected.md b/website/docs/cli/commands/describe/describe-affected.md index d5e8ac37e..49ff2439c 100644 --- a/website/docs/cli/commands/describe/describe-affected.md +++ b/website/docs/cli/commands/describe/describe-affected.md @@ -10,7 +10,7 @@ description: This command produces a list of the affected Atmos components and s Use this command to show a list of the affected Atmos components and stacks given two Git commits. For the first commit, the command assumes that the repo root is a Git checkout. -The second commit SHA is specified on the command line using the `--base` flag. +The second commit is specified on the command line using the `--ref` and `--sha` flags. ::: ## Usage @@ -28,16 +28,20 @@ Run `atmos describe affected --help` to see all the available options ## Examples ```shell -atmos describe affected --base origin/main -atmos describe affected --base origin/main --format json -atmos describe affected --base origin/main --file affected.json -atmos describe affected --base origin/main --file affected.yaml --format yaml +atmos describe affected --ref refs/heads/main +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 --ref refs/heads/my-new-branch --sha 3a5eafeab90426bd82bf5899896b28cc0bab3073 +atmos describe affected --ref refs/heads/my-new-branch --sha 3a5eafeab90426bd82bf5899896b28cc0bab3073 --file affected.json +atmos describe affected --sha 3a5eafeab90426bd82bf5899896b28cc0bab3073 ``` ## Flags -| Flag | Description | Required | -|:-----------|:----------------------------------------------------------------|:---------| -| `--base` | The SHA of a Git commit to compare the current Git checkout to | yes | -| `--file` | If specified, write the result to the file | no | -| `--format` | Specify the output format: `json` or `yaml` (`json` is default) | no | +| Flag | Description | Required | +|:------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------| +| `--ref` | Git reference with which to compare the current branch. Refer to [Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References) for more details | Either `--ref` or `--sha` is required. Both can be specified | +| `--sha` | Git commit SHA with which to compare the current branch | Either `--ref` or `--sha` is required. Both can be specified | +| `--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 | no | From 97b2313f6f82ea0e5dc71f6754fa67d336cba042 Mon Sep 17 00:00:00 2001 From: aknysh Date: Tue, 13 Dec 2022 21:57:01 -0500 Subject: [PATCH 09/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 29 ++++++++++++++++------------- pkg/config/schema.go | 8 ++++++++ 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 3667f104f..ff255905c 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -72,17 +72,17 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { } if format == "yaml" { - //if file == "" { - // err = u.PrintAsYAML(affected) - // if err != nil { - // return err - // } - //} else { - // err = u.WriteToFileAsYAML(file, affected, 0644) - // if err != nil { - // return err - // } - //} + if file == "" { + err = u.PrintAsYAML(affected) + if err != nil { + return err + } + } else { + err = u.WriteToFileAsYAML(file, affected, 0644) + if err != nil { + return err + } + } } else if format == "json" { if file == "" { err = u.PrintAsJSON(affected) @@ -106,7 +106,7 @@ func ExecuteDescribeAffected( ref string, sha string, verbose bool, -) (map[string]any, error) { +) ([]cfg.Affected, error) { // Get the origin URL of the current branch repoUrl, err := gitconfig.OriginURL() @@ -132,6 +132,7 @@ func ExecuteDescribeAffected( // Clone the remote repo // https://git-scm.com/book/en/v2/Git-Internals-Git-References + // 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 @@ -184,10 +185,12 @@ func ExecuteDescribeAffected( } } - affected, err := ExecuteDescribeStacks(cliConfig, "", nil, nil, nil) + _, err = ExecuteDescribeStacks(cliConfig, "", nil, nil, nil) if err != nil { return nil, err } + affected := []cfg.Affected{{}} + return affected, nil } diff --git a/pkg/config/schema.go b/pkg/config/schema.go index d3e1c088c..94a561433 100644 --- a/pkg/config/schema.go +++ b/pkg/config/schema.go @@ -327,3 +327,11 @@ type ValidationItem struct { } type Validation map[string]ValidationItem + +// Affected Atmos components and stacks given two Git commits + +type Affected struct { + Component string `yaml:"component" json:"component" mapstructure:"component"` + ComponentType string `yaml:"component_type" json:"component_type" mapstructure:"component_type"` + Stack string `yaml:"stack" json:"stack" mapstructure:"stack"` +} From f9ade38a02b5cd0827c6facf211d256173dd1047 Mon Sep 17 00:00:00 2001 From: aknysh Date: Tue, 13 Dec 2022 23:29:31 -0500 Subject: [PATCH 10/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 41 ++++++++++++++++++++++-------- pkg/config/schema.go | 4 +-- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index ff255905c..d2577bf00 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -8,6 +8,8 @@ import ( "github.com/spf13/cobra" "github.com/tcnksm/go-gitconfig" "os" + "path" + "reflect" "strconv" "time" @@ -136,9 +138,7 @@ func ExecuteDescribeAffected( // 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 - if verbose { - u.PrintInfo(fmt.Sprintf("\nCloning repo '%s' into a temp dir", repoUrl)) - } + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nCloning repo '%s' into a temp dir '%s'", repoUrl, tempDir)) cloneOptions := git.CloneOptions{ URL: repoUrl, @@ -148,9 +148,7 @@ func ExecuteDescribeAffected( if ref != "" { cloneOptions.ReferenceName = plumbing.ReferenceName(ref) - if verbose { - u.PrintInfo(fmt.Sprintf("Git ref: %s", ref)) - } + u.PrintInfoVerbose(verbose, fmt.Sprintf("Git ref: %s", ref)) } if verbose { cloneOptions.Progress = os.Stdout @@ -163,9 +161,7 @@ func ExecuteDescribeAffected( // Check if a commit SHA was provided and checkout the repo at that commit SHA if sha != "" { - if verbose { - u.PrintInfo(fmt.Sprintf("\nChecking out SHA: %s\n", sha)) - } + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecking out SHA: %s\n", sha)) w, err := repo.Worktree() if err != nil { @@ -185,12 +181,37 @@ func ExecuteDescribeAffected( } } - _, err = ExecuteDescribeStacks(cliConfig, "", nil, nil, nil) + currentStacks, err := FindStacksMap(cliConfig) + if err != nil { + return nil, err + } + + // Point base path 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 := FindStacksMap(cliConfig) if err != nil { return nil, err } + res := findAffected(currentStacks, remoteStacks) + u.PrintInfo(fmt.Sprintf("%v", res)) + affected := []cfg.Affected{{}} return affected, nil } + +func findAffected(currentStacks map[string]any, remoteStacks map[string]any) bool { + return reflect.DeepEqual(currentStacks, remoteStacks) +} diff --git a/pkg/config/schema.go b/pkg/config/schema.go index 94a561433..60f37d124 100644 --- a/pkg/config/schema.go +++ b/pkg/config/schema.go @@ -331,7 +331,7 @@ type Validation map[string]ValidationItem // Affected Atmos components and stacks given two Git commits type Affected struct { - Component string `yaml:"component" json:"component" mapstructure:"component"` - ComponentType string `yaml:"component_type" json:"component_type" mapstructure:"component_type"` 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"` } From 85577afc11724321e9ad87b3ff79c83a0ce2abdc Mon Sep 17 00:00:00 2001 From: aknysh Date: Tue, 13 Dec 2022 23:46:25 -0500 Subject: [PATCH 11/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index d2577bf00..85983193d 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -181,12 +181,12 @@ func ExecuteDescribeAffected( } } - currentStacks, err := FindStacksMap(cliConfig) + currentStacks, err := ExecuteDescribeStacks(cliConfig, "", nil, nil, nil) if err != nil { return nil, err } - // Point base path to the temp dir + // 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) @@ -199,7 +199,7 @@ func ExecuteDescribeAffected( return nil, err } - remoteStacks, err := FindStacksMap(cliConfig) + remoteStacks, err := ExecuteDescribeStacks(cliConfig, "", nil, nil, nil) if err != nil { return nil, err } From 68981fb750cb33d76a23b0dbf31f6df9ffa3218b Mon Sep 17 00:00:00 2001 From: aknysh Date: Tue, 13 Dec 2022 23:51:21 -0500 Subject: [PATCH 12/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 85983193d..7fa8fa7e1 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -9,7 +9,6 @@ import ( "github.com/tcnksm/go-gitconfig" "os" "path" - "reflect" "strconv" "time" @@ -204,14 +203,10 @@ func ExecuteDescribeAffected( return nil, err } - res := findAffected(currentStacks, remoteStacks) - u.PrintInfo(fmt.Sprintf("%v", res)) - - affected := []cfg.Affected{{}} - + affected := findAffected(currentStacks, remoteStacks) return affected, nil } -func findAffected(currentStacks map[string]any, remoteStacks map[string]any) bool { - return reflect.DeepEqual(currentStacks, remoteStacks) +func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []cfg.Affected { + return []cfg.Affected{} } From 12ba1eb950539de7e6c6d659acf6b7200c0ccc98 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 00:45:49 -0500 Subject: [PATCH 13/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 7fa8fa7e1..5e8e8fc76 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -2,8 +2,11 @@ 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/google/go-cmp/cmp" "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/tcnksm/go-gitconfig" @@ -11,9 +14,6 @@ import ( "path" "strconv" "time" - - cfg "github.com/cloudposse/atmos/pkg/config" - u "github.com/cloudposse/atmos/pkg/utils" ) // ExecuteDescribeAffectedCmd executes `describe affected` command @@ -208,5 +208,9 @@ func ExecuteDescribeAffected( } func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []cfg.Affected { + if diff := cmp.Diff(currentStacks, remoteStacks); diff != "" { + fmt.Println(diff) + } + return []cfg.Affected{} } From 84a88ebbb03f4d6ee86820b2c5abadc5ba594881 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 01:19:51 -0500 Subject: [PATCH 14/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 57 +++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 5e8e8fc76..abdea5be5 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -6,7 +6,6 @@ import ( u "github.com/cloudposse/atmos/pkg/utils" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" - "github.com/google/go-cmp/cmp" "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/tcnksm/go-gitconfig" @@ -189,7 +188,6 @@ func ExecuteDescribeAffected( 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, @@ -208,9 +206,58 @@ func ExecuteDescribeAffected( } func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []cfg.Affected { - if diff := cmp.Diff(currentStacks, remoteStacks); diff != "" { - fmt.Println(diff) + 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 { + // Skip abstract components + if metadataSection, ok := componentSection["metadata"].(map[any]any); ok { + if metadataType, ok := metadataSection["type"].(string); ok { + if metadataType == "abstract" { + continue + } + } + } + if _, ok := componentSection["vars"].(map[any]any); ok { + affected := cfg.Affected{ + ComponentType: "terraform", + Component: componentName, + Stack: stackName, + } + res = append(res, affected) + } + } + } + } + if helmfileSection, ok := componentsSection["helmfile"].(map[string]any); ok { + for componentName, compSection := range helmfileSection { + if componentSection, ok := compSection.(map[string]any); ok { + // Skip abstract components + if metadataSection, ok := componentSection["metadata"].(map[any]any); ok { + if metadataType, ok := metadataSection["type"].(string); ok { + if metadataType == "abstract" { + continue + } + } + } + if _, ok := componentSection["vars"].(map[any]any); ok { + affected := cfg.Affected{ + ComponentType: "helmfile", + Component: componentName, + Stack: stackName, + } + res = append(res, affected) + } + } + } + } + } + } } - return []cfg.Affected{} + return res } From b7560da18e155fb754bef7d57b48005a3221873d Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 10:27:11 -0500 Subject: [PATCH 15/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 49 ++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index abdea5be5..8fd75730b 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -11,6 +11,7 @@ import ( "github.com/tcnksm/go-gitconfig" "os" "path" + "reflect" "strconv" "time" ) @@ -108,7 +109,7 @@ func ExecuteDescribeAffected( verbose bool, ) ([]cfg.Affected, error) { - // Get the origin URL of the current branch + // Get the origin URL of the current repo repoUrl, err := gitconfig.OriginURL() if err != nil { return nil, err @@ -222,13 +223,15 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c } } } - if _, ok := componentSection["vars"].(map[any]any); ok { - affected := cfg.Affected{ - ComponentType: "terraform", - Component: componentName, - Stack: stackName, + if varSection, ok := componentSection["vars"].(map[any]any); ok { + if !isEqual(remoteStacks, stackName, "terraform", componentName, varSection) { + affected := cfg.Affected{ + ComponentType: "terraform", + Component: componentName, + Stack: stackName, + } + res = append(res, affected) } - res = append(res, affected) } } } @@ -244,13 +247,15 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c } } } - if _, ok := componentSection["vars"].(map[any]any); ok { - affected := cfg.Affected{ - ComponentType: "helmfile", - Component: componentName, - Stack: stackName, + if varSection, ok := componentSection["vars"].(map[any]any); ok { + if !isEqual(remoteStacks, stackName, "helmfile", componentName, varSection) { + affected := cfg.Affected{ + ComponentType: "helmfile", + Component: componentName, + Stack: stackName, + } + res = append(res, affected) } - res = append(res, affected) } } } @@ -261,3 +266,21 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c return res } + +// isEqual compares the vars sections of the component from the remote stacks with the vars section of the current local component +func isEqual(remoteStacks map[string]any, stackName string, componentType string, componentName string, varSection map[any]any) bool { + if stackSection, ok := remoteStacks[stackName].(map[string]any); ok { + if componentsSection, ok := stackSection["components"].(map[string]any); ok { + if componentTypeSection, ok := componentsSection[componentType].(map[string]any); ok { + if componentSection, ok := componentTypeSection[componentName].(map[string]any); ok { + if componentVarSection, ok := componentSection["vars"].(map[any]any); ok { + if reflect.DeepEqual(varSection, componentVarSection) { + return true + } + } + } + } + } + } + return false +} From 419eb9e9350fa244343c351a9276472cd9f41af1 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 11:04:11 -0500 Subject: [PATCH 16/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 8fd75730b..9e139f227 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -268,13 +268,19 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c } // isEqual compares the vars sections of the component from the remote stacks with the vars section of the current local component -func isEqual(remoteStacks map[string]any, stackName string, componentType string, componentName string, varSection map[any]any) bool { - if stackSection, ok := remoteStacks[stackName].(map[string]any); ok { - if componentsSection, ok := stackSection["components"].(map[string]any); ok { - if componentTypeSection, ok := componentsSection[componentType].(map[string]any); ok { - if componentSection, ok := componentTypeSection[componentName].(map[string]any); ok { - if componentVarSection, ok := componentSection["vars"].(map[any]any); ok { - if reflect.DeepEqual(varSection, componentVarSection) { +func isEqual( + remoteStacks map[string]any, + localStackName string, + componentType string, + localComponentName string, + localVarSection map[any]any) 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 remoteComponentVarSection, ok := remoteComponentSection["vars"].(map[any]any); ok { + if reflect.DeepEqual(localVarSection, remoteComponentVarSection) { return true } } From c1173e81cbd10d79f89e89ddb11dd00552eeda4e Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 11:14:56 -0500 Subject: [PATCH 17/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 9e139f227..0596c09ef 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -224,13 +224,14 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c } } if varSection, ok := componentSection["vars"].(map[any]any); ok { - if !isEqual(remoteStacks, stackName, "terraform", componentName, varSection) { + if !isEqual(remoteStacks, stackName, "terraform", componentName, varSection, "vars") { affected := cfg.Affected{ ComponentType: "terraform", Component: componentName, Stack: stackName, } res = append(res, affected) + continue } } } @@ -248,13 +249,14 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c } } if varSection, ok := componentSection["vars"].(map[any]any); ok { - if !isEqual(remoteStacks, stackName, "helmfile", componentName, varSection) { + if !isEqual(remoteStacks, stackName, "helmfile", componentName, varSection, "vars") { affected := cfg.Affected{ ComponentType: "helmfile", Component: componentName, Stack: stackName, } res = append(res, affected) + continue } } } @@ -267,20 +269,21 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c return res } -// isEqual compares the vars sections of the component from the remote stacks with the vars section of the current local component +// 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, - localVarSection map[any]any) bool { + 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 remoteComponentVarSection, ok := remoteComponentSection["vars"].(map[any]any); ok { - if reflect.DeepEqual(localVarSection, remoteComponentVarSection) { + if remoteSection, ok := remoteComponentSection[sectionName].(map[any]any); ok { + if reflect.DeepEqual(localSection, remoteSection) { return true } } From 3937ed5b6ae064cc2f571a853132ac38c89b036e Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 11:21:55 -0500 Subject: [PATCH 18/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 0596c09ef..e9e6f2dc2 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -223,6 +223,7 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c } } } + // Check `vars` section if varSection, ok := componentSection["vars"].(map[any]any); ok { if !isEqual(remoteStacks, stackName, "terraform", componentName, varSection, "vars") { affected := cfg.Affected{ @@ -234,6 +235,18 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c 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, + } + res = append(res, affected) + continue + } + } } } } @@ -248,6 +261,7 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c } } } + // Check `vars` section if varSection, ok := componentSection["vars"].(map[any]any); ok { if !isEqual(remoteStacks, stackName, "helmfile", componentName, varSection, "vars") { affected := cfg.Affected{ @@ -259,6 +273,18 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c 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, + } + res = append(res, affected) + continue + } + } } } } From d0eafe67ccba92c0357eb4c109f825eebf88e9ed Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 11:48:04 -0500 Subject: [PATCH 19/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 31 +++++++++++++++++------------- pkg/config/schema.go | 7 ++++--- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index e9e6f2dc2..d04f8344f 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -227,9 +227,10 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c 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, + ComponentType: "terraform", + Component: componentName, + Stack: stackName, + AffectedSection: "vars", } res = append(res, affected) continue @@ -239,9 +240,10 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c 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, + ComponentType: "terraform", + Component: componentName, + Stack: stackName, + AffectedSection: "env", } res = append(res, affected) continue @@ -265,9 +267,10 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c 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, + ComponentType: "helmfile", + Component: componentName, + Stack: stackName, + AffectedSection: "vars", } res = append(res, affected) continue @@ -277,9 +280,10 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c 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, + ComponentType: "helmfile", + Component: componentName, + Stack: stackName, + AffectedSection: "env", } res = append(res, affected) continue @@ -302,7 +306,8 @@ func isEqual( componentType string, localComponentName string, localSection map[any]any, - sectionName string) bool { + sectionName string, +) bool { if remoteStackSection, ok := remoteStacks[localStackName].(map[string]any); ok { if remoteComponentsSection, ok := remoteStackSection["components"].(map[string]any); ok { diff --git a/pkg/config/schema.go b/pkg/config/schema.go index 60f37d124..6b6addc19 100644 --- a/pkg/config/schema.go +++ b/pkg/config/schema.go @@ -331,7 +331,8 @@ 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"` + 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"` + AffectedSection string `yaml:"affected_section" json:"affected_section" mapstructure:"affected_section"` } From 13cc1eaa57584b2754d304b5f62833cd3b38eb9f Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 12:48:52 -0500 Subject: [PATCH 20/47] Add `atmos describe affected` command --- pkg/describe/describe_affected_test.go | 33 +++++++++++++++++++ ...ent_test.go => describe_component_test.go} | 0 website/.nvmrc | 2 +- 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 pkg/describe/describe_affected_test.go rename pkg/describe/{terraform_describe_component_test.go => describe_component_test.go} (100%) diff --git a/pkg/describe/describe_affected_test.go b/pkg/describe/describe_affected_test.go new file mode 100644 index 000000000..8fa78a53a --- /dev/null +++ b/pkg/describe/describe_affected_test.go @@ -0,0 +1,33 @@ +package describe + +import ( + 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) + + componentSectionYaml, err := yaml.Marshal(affected) + assert.Nil(t, err) + t.Log(string(componentSectionYaml)) +} 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/website/.nvmrc b/website/.nvmrc index 2a4e4ab81..b460d6f2d 100644 --- a/website/.nvmrc +++ b/website/.nvmrc @@ -1 +1 @@ -16.17.0 +18.12.1 From 6c603580cb02ae953fc5d3c53df83edc66e300c3 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 14:21:29 -0500 Subject: [PATCH 21/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index d04f8344f..1934b040d 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -147,7 +147,7 @@ func ExecuteDescribeAffected( if ref != "" { cloneOptions.ReferenceName = plumbing.ReferenceName(ref) - u.PrintInfoVerbose(verbose, fmt.Sprintf("Git ref: %s", ref)) + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecking out Git ref: %s\n", ref)) } if verbose { cloneOptions.Progress = os.Stdout From 5f18e6f564eaca2c7a1dccf69037641a70716c1d Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 15:08:45 -0500 Subject: [PATCH 22/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 33 +++++++------------------- internal/exec/describe_stacks.go | 31 ++++++------------------- internal/exec/utils.go | 37 ++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 49 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 1934b040d..ea2dd5b04 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -43,16 +43,18 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { } if ref == "" && sha == "" { - return fmt.Errorf("invalid flag. Either '--ref' or '--sha' is required. Both can be specified") + return fmt.Errorf("invalid flags. Either '--ref' or '--sha' is required. Both can be specified") } 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 'yaml' (default) and 'json'", format) } + if format == "" { format = "json" } @@ -72,30 +74,9 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { return err } - if format == "yaml" { - if file == "" { - err = u.PrintAsYAML(affected) - if err != nil { - return err - } - } else { - err = u.WriteToFileAsYAML(file, affected, 0644) - if err != nil { - return err - } - } - } else if format == "json" { - if file == "" { - err = u.PrintAsJSON(affected) - if err != nil { - return err - } - } else { - err = u.WriteToFileAsJSON(file, affected, 0644) - if err != nil { - return err - } - } + err = printOrWriteToFile(format, file, affected) + if err != nil { + return err } return nil @@ -149,6 +130,7 @@ func ExecuteDescribeAffected( cloneOptions.ReferenceName = plumbing.ReferenceName(ref) u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecking out Git ref: %s\n", ref)) } + if verbose { cloneOptions.Progress = os.Stdout } @@ -189,6 +171,7 @@ func ExecuteDescribeAffected( 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, diff --git a/internal/exec/describe_stacks.go b/internal/exec/describe_stacks.go index 59e80a0c1..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, ",") @@ -78,30 +82,9 @@ func ExecuteDescribeStacksCmd(cmd *cobra.Command, args []string) error { return err } - 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 - } - } + err = printOrWriteToFile(format, file, finalStacksMap) + if err != nil { + return err } return nil diff --git a/internal/exec/utils.go b/internal/exec/utils.go index ddb99367b..1c293c538 100644 --- a/internal/exec/utils.go +++ b/internal/exec/utils.go @@ -674,3 +674,40 @@ 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 +} From 1bdac55c74482ec446c8cc0b288b688f7a006ab4 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 15:15:24 -0500 Subject: [PATCH 23/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 8 ++------ internal/exec/utils.go | 8 ++++++++ internal/exec/vendor_utils.go | 7 +------ 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index ea2dd5b04..1865a284f 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -95,6 +95,7 @@ func ExecuteDescribeAffected( if err != nil { return nil, err } + if repoUrl == "" { return nil, errors.New("the current repo is not a Git repository. Check that it was initialized and has '.git' folder") } @@ -105,12 +106,7 @@ func ExecuteDescribeAffected( return nil, err } - defer func(path string) { - err := os.RemoveAll(path) - if err != nil { - u.PrintError(err) - } - }(tempDir) + defer removeTempDir(tempDir) // Clone the remote repo // https://git-scm.com/book/en/v2/Git-Internals-Git-References diff --git a/internal/exec/utils.go b/internal/exec/utils.go index 1c293c538..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" @@ -711,3 +712,10 @@ func printOrWriteToFile(format string, file string, data any) error { 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{ From 4b6a45bde9b12cbbe11b839c6eba353dfeccf346 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 15:27:17 -0500 Subject: [PATCH 24/47] Add `atmos describe affected` command --- internal/exec/describe_component.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/internal/exec/describe_component.go b/internal/exec/describe_component.go index 0d384cf47..c30f0ab2f 100644 --- a/internal/exec/describe_component.go +++ b/internal/exec/describe_component.go @@ -60,10 +60,14 @@ func ExecuteDescribeComponent(component string, stack string) (map[string]any, e } } - // Always add component, base component (if any) and stack to the `atmos describe component` command output - configAndStacksInfo.ComponentSection["component"] = configAndStacksInfo.ComponentFromArg - configAndStacksInfo.ComponentSection["base_component"] = configAndStacksInfo.BaseComponent - configAndStacksInfo.ComponentSection["stack"] = configAndStacksInfo.StackFromArg + // 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 } From ad021c055e2fd5fadf0ac1493856eccf16236d0f Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 15:35:15 -0500 Subject: [PATCH 25/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 34 ++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 1865a284f..b0015912b 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -42,17 +42,13 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { return err } - if ref == "" && sha == "" { - return fmt.Errorf("invalid flags. Either '--ref' or '--sha' is required. Both can be specified") - } - 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 'yaml' (default) and 'json'", format) + return fmt.Errorf("invalid '--format' flag '%s'. Valid values are 'json' (default) and 'yaml'", format) } if format == "" { @@ -114,7 +110,7 @@ func ExecuteDescribeAffected( // 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 - u.PrintInfoVerbose(verbose, fmt.Sprintf("\nCloning repo '%s' into a temp dir '%s'", repoUrl, tempDir)) + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nCloning repo '%s' into the temp dir '%s'", repoUrl, tempDir)) cloneOptions := git.CloneOptions{ URL: repoUrl, @@ -228,6 +224,19 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c 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, + AffectedSection: "settings", + } + res = append(res, affected) + continue + } + } } } } @@ -268,6 +277,19 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c 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, + AffectedSection: "settings", + } + res = append(res, affected) + continue + } + } } } } From 78b89a3dc33d7c8e07c276a8690b2b453ed9bec3 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 16:38:56 -0500 Subject: [PATCH 26/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 19 ++++++++++++++++++- .../commands/describe/describe-affected.md | 17 ++++++++++------- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index b0015912b..1cca793fe 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -106,6 +106,7 @@ func ExecuteDescribeAffected( // 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 @@ -118,9 +119,12 @@ func ExecuteDescribeAffected( 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 { @@ -132,9 +136,20 @@ func ExecuteDescribeAffected( return nil, err } + head, err := repo.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", head.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 SHA: %s\n", sha)) + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecking out commit SHA: %s\n", sha)) w, err := repo.Worktree() if err != nil { @@ -152,6 +167,8 @@ func ExecuteDescribeAffected( 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) diff --git a/website/docs/cli/commands/describe/describe-affected.md b/website/docs/cli/commands/describe/describe-affected.md index 49ff2439c..2527dd605 100644 --- a/website/docs/cli/commands/describe/describe-affected.md +++ b/website/docs/cli/commands/describe/describe-affected.md @@ -10,7 +10,9 @@ description: This command produces a list of the affected Atmos components and s Use this command to show a list of the affected Atmos components and stacks given two Git commits. For the first commit, the command assumes that the repo root is a Git checkout. + The second commit is specified on the command line using the `--ref` and `--sha` flags. +If the flags are not provided, it will clone the HEAD of the default branch. ::: ## Usage @@ -28,6 +30,7 @@ Run `atmos describe affected --help` to see all the available options ## Examples ```shell +atmos describe affected atmos describe affected --ref refs/heads/main atmos describe affected --ref refs/heads/main --format json atmos describe affected --ref refs/tags/v1.16.0 --file affected.yaml --format yaml @@ -38,10 +41,10 @@ atmos describe affected --sha 3a5eafeab90426bd82bf5899896b28cc0bab3073 ## Flags -| Flag | Description | Required | -|:------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------| -| `--ref` | Git reference with which to compare the current branch. Refer to [Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References) for more details | Either `--ref` or `--sha` is required. Both can be specified | -| `--sha` | Git commit SHA with which to compare the current branch | Either `--ref` or `--sha` is required. Both can be specified | -| `--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 | no | +| Flag | Description | Required | +|:------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------| +| `--ref` | Git reference with which to compare the current branch. Refer to [Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References) for more details | no | +| `--sha` | Git commit SHA with which to compare the current 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 | no | From c746fc6ba1f0e6c280378ec7cd6cf09ec234b763 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 17:36:54 -0500 Subject: [PATCH 27/47] Add `atmos describe affected` command --- cmd/describe_affected.go | 2 +- .../docs/cli/commands/describe/describe-affected.md | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/cmd/describe_affected.go b/cmd/describe_affected.go index 88d81a2a6..e037ddbe2 100644 --- a/cmd/describe_affected.go +++ b/cmd/describe_affected.go @@ -25,7 +25,7 @@ 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 --ref refs/heads/my-new-branch --sha 3a5eafeab90426bd82bf5899896b28cc0bab3073") + 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 --ref refs/heads/main --format=json|yaml ('json' is default)") describeAffectedCmd.PersistentFlags().Bool("verbose", false, "atmos describe affected --ref refs/heads/main --verbose=true") diff --git a/website/docs/cli/commands/describe/describe-affected.md b/website/docs/cli/commands/describe/describe-affected.md index 2527dd605..31c79290f 100644 --- a/website/docs/cli/commands/describe/describe-affected.md +++ b/website/docs/cli/commands/describe/describe-affected.md @@ -8,10 +8,15 @@ description: This command produces a list of the affected Atmos components and s :::note Purpose Use this command to show a list of the affected Atmos components and stacks given two Git commits. +::: + +
+:::info For the first commit, the command assumes that the repo root is a Git checkout. -The second commit is specified on the command line using the `--ref` and `--sha` flags. +The second commit is specified on the command line by using the `--ref` or `--sha` flags. + If the flags are not provided, it will clone the HEAD of the default branch. ::: @@ -32,10 +37,10 @@ Run `atmos describe affected --help` to see all the available options ```shell atmos describe affected 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 --ref refs/heads/my-new-branch --sha 3a5eafeab90426bd82bf5899896b28cc0bab3073 -atmos describe affected --ref refs/heads/my-new-branch --sha 3a5eafeab90426bd82bf5899896b28cc0bab3073 --file affected.json +atmos describe affected --sha 3a5eafeab90426bd82bf5899896b28cc0bab3073 --file affected.json atmos describe affected --sha 3a5eafeab90426bd82bf5899896b28cc0bab3073 ``` From 6ab91cb31ba4d8e90ddefee675beb5164e07beb5 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 17:52:52 -0500 Subject: [PATCH 28/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 1cca793fe..c488756fc 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -207,13 +207,24 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c if terraformSection, ok := componentsSection["terraform"].(map[string]any); ok { for componentName, compSection := range terraformSection { if componentSection, ok := compSection.(map[string]any); ok { - // Skip abstract components 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, + AffectedSection: "metadata", + } + res = append(res, affected) + continue + } } // Check `vars` section if varSection, ok := componentSection["vars"].(map[any]any); ok { @@ -260,13 +271,24 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c if helmfileSection, ok := componentsSection["helmfile"].(map[string]any); ok { for componentName, compSection := range helmfileSection { if componentSection, ok := compSection.(map[string]any); ok { - // Skip abstract components 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, + AffectedSection: "metadata", + } + res = append(res, affected) + continue + } } // Check `vars` section if varSection, ok := componentSection["vars"].(map[any]any); ok { From 4e8e53fbf549d0d9ca3af0e784e193701010c060 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 18:49:02 -0500 Subject: [PATCH 29/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index c488756fc..fc33b8ace 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -198,6 +198,7 @@ func ExecuteDescribeAffected( return affected, nil } +// findAffected returns a list of all affected components in all stacks func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []cfg.Affected { res := []cfg.Affected{} From 46b9ae6e71f6f86df5fddf04ce4400ea22ee6d7c Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 19:59:08 -0500 Subject: [PATCH 30/47] Add `atmos describe affected` command --- go.mod | 2 -- go.sum | 4 --- internal/exec/describe_affected.go | 43 +++++++++++++++++++++++------- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 42691185b..bd81eea00 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,6 @@ require ( github.com/spf13/cobra v1.6.1 github.com/spf13/viper v1.14.0 github.com/stretchr/testify v1.8.1 - github.com/tcnksm/go-gitconfig v0.1.2 github.com/zclconf/go-cty v1.12.1 gopkg.in/yaml.v2 v2.4.0 mvdan.cc/sh/v3 v3.6.0 @@ -92,7 +91,6 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/morikuni/aec v1.0.0 // indirect - github.com/onsi/gomega v1.24.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect github.com/pelletier/go-toml v1.9.5 // indirect diff --git a/go.sum b/go.sum index bc1f45e87..d09fac4d8 100644 --- a/go.sum +++ b/go.sum @@ -434,8 +434,6 @@ github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7P 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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= -github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= 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= @@ -542,8 +540,6 @@ github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= -github.com/tcnksm/go-gitconfig v0.1.2 h1:iiDhRitByXAEyjgBqsKi9QU4o2TNtv9kPP3RgPgXBPw= -github.com/tcnksm/go-gitconfig v0.1.2/go.mod h1:/8EhP4H7oJZdIPyT+/UIsG87kTzrzM4UsLGSItWYCpE= 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= diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index fc33b8ace..a9a2d8754 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -8,7 +8,6 @@ import ( "github.com/go-git/go-git/v5/plumbing" "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/tcnksm/go-gitconfig" "os" "path" "reflect" @@ -86,23 +85,41 @@ func ExecuteDescribeAffected( verbose bool, ) ([]cfg.Affected, error) { - // Get the origin URL of the current repo - repoUrl, err := gitconfig.OriginURL() + localRepo, err := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{ + DetectDotGit: true, + EnableDotGitCommonDir: false, + }) if err != nil { return nil, err } - if repoUrl == "" { - return nil, errors.New("the current repo is not a Git repository. Check that it was initialized and has '.git' folder") - } + repoIsNotGitRepoError := errors.New("the current repo is not a Git repository. Check that it was initialized and has '.git' folder") - // Create a temp dir to clone the remote repo to - tempDir, err := os.MkdirTemp("", strconv.FormatInt(time.Now().Unix(), 10)) + // Get the Git config of the current repo + localRepoConfig, err := localRepo.Config() if err != nil { return nil, err } - defer removeTempDir(tempDir) + 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 repo + remoteUrls := localRepoConfig.Remotes[keys[0]].URLs + if len(remoteUrls) == 0 { + return nil, repoIsNotGitRepoError + } + + repoUrl := remoteUrls[0] + if repoUrl == "" { + return nil, repoIsNotGitRepoError + } // Clone the remote repo // https://git-scm.com/book/en/v2/Git-Internals-Git-References @@ -111,6 +128,14 @@ func ExecuteDescribeAffected( // 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 + // 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{ From 517fc690a6925c949644b1a03594f529c6a9dde4 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 20:12:35 -0500 Subject: [PATCH 31/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index a9a2d8754..358e9c4a8 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -69,6 +69,8 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { return err } + u.PrintInfoVerbose(verbose && file == "", fmt.Sprintf("Affected: \n")) + err = printOrWriteToFile(format, file, affected) if err != nil { return err @@ -93,9 +95,9 @@ func ExecuteDescribeAffected( return nil, err } - repoIsNotGitRepoError := errors.New("the current repo is not a Git repository. Check that it was initialized and has '.git' folder") + repoIsNotGitRepoError := errors.New("the current remoteRepo is not a Git repository. Check that it was initialized and has '.git' folder") - // Get the Git config of the current repo + // Get the Git config of the current remoteRepo localRepoConfig, err := localRepo.Config() if err != nil { return nil, err @@ -110,7 +112,7 @@ func ExecuteDescribeAffected( return nil, repoIsNotGitRepoError } - // Get the origin URL of the current repo + // Get the origin URL of the current remoteRepo remoteUrls := localRepoConfig.Remotes[keys[0]].URLs if len(remoteUrls) == 0 { return nil, repoIsNotGitRepoError @@ -121,6 +123,11 @@ func ExecuteDescribeAffected( 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 @@ -156,12 +163,12 @@ func ExecuteDescribeAffected( cloneOptions.Progress = os.Stdout } - repo, err := git.PlainClone(tempDir, false, &cloneOptions) + remoteRepo, err := git.PlainClone(tempDir, false, &cloneOptions) if err != nil { return nil, err } - head, err := repo.Head() + remoteRepoHead, err := remoteRepo.Head() if err != nil { return nil, err } @@ -169,14 +176,14 @@ func ExecuteDescribeAffected( 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", head.Name())) + 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 + // Check if a commit SHA was provided and checkout the remoteRepo at that commit SHA if sha != "" { u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecking out commit SHA: %s\n", sha)) - w, err := repo.Worktree() + w, err := remoteRepo.Worktree() if err != nil { return nil, err } @@ -196,6 +203,11 @@ func ExecuteDescribeAffected( u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out commit SHA: %s\n", sha)) } + if verbose { + u.PrintInfo(fmt.Sprintf("Local repo HEAD: %s", localRepoHead)) + u.PrintInfo(fmt.Sprintf("Remote repo HEAD: %s\n", remoteRepoHead)) + } + currentStacks, err := ExecuteDescribeStacks(cliConfig, "", nil, nil, nil) if err != nil { return nil, err From 325f340f4d500a976cb2bf37864bd648c486d069 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 20:13:18 -0500 Subject: [PATCH 32/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 358e9c4a8..70a9f4109 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -95,7 +95,7 @@ func ExecuteDescribeAffected( return nil, err } - repoIsNotGitRepoError := errors.New("the current remoteRepo is not a Git repository. Check that it was initialized and has '.git' folder") + 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() @@ -179,7 +179,7 @@ func ExecuteDescribeAffected( u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out Git ref: %s\n", remoteRepoHead.Name())) } - // Check if a commit SHA was provided and checkout the remoteRepo at that commit SHA + // 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)) From bbc5f69cd745927054a66331591ee7151eaa2c42 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 21:07:49 -0500 Subject: [PATCH 33/47] Add `atmos describe affected` command --- .../components/terraform/infra/vpc/main.tf | 1 + internal/exec/describe_affected.go | 41 ++++++++++++++++--- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/examples/complete/components/terraform/infra/vpc/main.tf b/examples/complete/components/terraform/infra/vpc/main.tf index c863b6193..a963adaff 100644 --- a/examples/complete/components/terraform/infra/vpc/main.tf +++ b/examples/complete/components/terraform/infra/vpc/main.tf @@ -62,3 +62,4 @@ module "subnets" { context = module.this.context } + diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 70a9f4109..190577b81 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -69,7 +69,7 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error { return err } - u.PrintInfoVerbose(verbose && file == "", fmt.Sprintf("Affected: \n")) + u.PrintInfoVerbose(verbose && file == "", fmt.Sprintf("\nAffected components and stacks: \n")) err = printOrWriteToFile(format, file, affected) if err != nil { @@ -203,11 +203,6 @@ func ExecuteDescribeAffected( u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out commit SHA: %s\n", sha)) } - if verbose { - u.PrintInfo(fmt.Sprintf("Local repo HEAD: %s", localRepoHead)) - u.PrintInfo(fmt.Sprintf("Remote repo HEAD: %s\n", remoteRepoHead)) - } - currentStacks, err := ExecuteDescribeStacks(cliConfig, "", nil, nil, nil) if err != nil { return nil, err @@ -231,6 +226,40 @@ func ExecuteDescribeAffected( return nil, err } + if verbose { + u.PrintInfo(fmt.Sprintf("Local repo HEAD: %s", localRepoHead)) + u.PrintInfo(fmt.Sprintf("Remote repo HEAD: %s", remoteRepoHead)) + } + + localCommit, err := localRepo.CommitObject(localRepoHead.Hash()) + if err != nil { + return nil, err + } + + localTree, err := localCommit.Tree() + if err != nil { + return nil, err + } + + remoteCommit, err := localRepo.CommitObject(remoteRepoHead.Hash()) + if err != nil { + return nil, err + } + + remoteTree, err := remoteCommit.Tree() + if err != nil { + return nil, err + } + + patch, err := localTree.Patch(remoteTree) + + 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) return affected, nil } From f376f1989e742558eda6072117cdefd42d0eb69f Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 21:21:20 -0500 Subject: [PATCH 34/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 190577b81..e4bc60cf9 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -134,6 +134,8 @@ func ExecuteDescribeAffected( // 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)) From 8636adbdfc9690d2b57f2e32ac6a957b0439f0bb Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 21:21:38 -0500 Subject: [PATCH 35/47] Add `atmos describe affected` command --- .../components/terraform/infra/vpc/context.tf | 279 ------------------ 1 file changed, 279 deletions(-) delete mode 100644 examples/complete/components/terraform/infra/vpc/context.tf diff --git a/examples/complete/components/terraform/infra/vpc/context.tf b/examples/complete/components/terraform/infra/vpc/context.tf deleted file mode 100644 index 5e0ef8856..000000000 --- a/examples/complete/components/terraform/infra/vpc/context.tf +++ /dev/null @@ -1,279 +0,0 @@ -# -# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label -# All other instances of this file should be a copy of that one -# -# -# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf -# and then place it in your Terraform module to automatically get -# Cloud Posse's standard configuration inputs suitable for passing -# to Cloud Posse modules. -# -# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf -# -# Modules should access the whole context as `module.this.context` -# to get the input variables with nulls for defaults, -# for example `context = module.this.context`, -# and access individual variables as `module.this.`, -# with final values filled in. -# -# For example, when using defaults, `module.this.context.delimiter` -# will be null, and `module.this.delimiter` will be `-` (hyphen). -# - -module "this" { - source = "cloudposse/label/null" - version = "0.25.0" # requires Terraform >= 0.13.0 - - enabled = var.enabled - namespace = var.namespace - tenant = var.tenant - environment = var.environment - stage = var.stage - name = var.name - delimiter = var.delimiter - attributes = var.attributes - tags = var.tags - additional_tag_map = var.additional_tag_map - label_order = var.label_order - regex_replace_chars = var.regex_replace_chars - id_length_limit = var.id_length_limit - label_key_case = var.label_key_case - label_value_case = var.label_value_case - descriptor_formats = var.descriptor_formats - labels_as_tags = var.labels_as_tags - - context = var.context -} - -# Copy contents of cloudposse/terraform-null-label/variables.tf here - -variable "context" { - type = any - default = { - enabled = true - namespace = null - tenant = null - environment = null - stage = null - name = null - delimiter = null - attributes = [] - tags = {} - additional_tag_map = {} - regex_replace_chars = null - label_order = [] - id_length_limit = null - label_key_case = null - label_value_case = null - descriptor_formats = {} - # Note: we have to use [] instead of null for unset lists due to - # https://github.com/hashicorp/terraform/issues/28137 - # which was not fixed until Terraform 1.0.0, - # but we want the default to be all the labels in `label_order` - # and we want users to be able to prevent all tag generation - # by setting `labels_as_tags` to `[]`, so we need - # a different sentinel to indicate "default" - labels_as_tags = ["unset"] - } - description = <<-EOT - Single object for setting entire context at once. - See description of individual variables for details. - Leave string and numeric variables as `null` to use default value. - Individual variable settings (non-null) override settings in context object, - except for attributes, tags, and additional_tag_map, which are merged. - EOT - - validation { - condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) - error_message = "Allowed values: `lower`, `title`, `upper`." - } - - validation { - condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) - error_message = "Allowed values: `lower`, `title`, `upper`, `none`." - } -} - -variable "enabled" { - type = bool - default = null - description = "Set to false to prevent the module from creating any resources" -} - -variable "namespace" { - type = string - default = null - description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" -} - -variable "tenant" { - type = string - default = null - description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" -} - -variable "environment" { - type = string - default = null - description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" -} - -variable "stage" { - type = string - default = null - description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" -} - -variable "name" { - type = string - default = null - description = <<-EOT - ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. - This is the only ID element not also included as a `tag`. - The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. - EOT -} - -variable "delimiter" { - type = string - default = null - description = <<-EOT - Delimiter to be used between ID elements. - Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. - EOT -} - -variable "attributes" { - type = list(string) - default = [] - description = <<-EOT - ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, - in the order they appear in the list. New attributes are appended to the - end of the list. The elements of the list are joined by the `delimiter` - and treated as a single ID element. - EOT -} - -variable "labels_as_tags" { - type = set(string) - default = ["default"] - description = <<-EOT - Set of labels (ID elements) to include as tags in the `tags` output. - Default is to include all labels. - Tags with empty values will not be included in the `tags` output. - Set to `[]` to suppress all generated tags. - **Notes:** - The value of the `name` tag, if included, will be the `id`, not the `name`. - Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be - changed in later chained modules. Attempts to change it will be silently ignored. - EOT -} - -variable "tags" { - type = map(string) - default = {} - description = <<-EOT - Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). - Neither the tag keys nor the tag values will be modified by this module. - EOT -} - -variable "additional_tag_map" { - type = map(string) - default = {} - description = <<-EOT - Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. - This is for some rare cases where resources want additional configuration of tags - and therefore take a list of maps with tag key, value, and additional configuration. - EOT -} - -variable "label_order" { - type = list(string) - default = null - description = <<-EOT - The order in which the labels (ID elements) appear in the `id`. - Defaults to ["namespace", "environment", "stage", "name", "attributes"]. - You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. - EOT -} - -variable "regex_replace_chars" { - type = string - default = null - description = <<-EOT - Terraform regular expression (regex) string. - Characters matching the regex will be removed from the ID elements. - If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. - EOT -} - -variable "id_length_limit" { - type = number - default = null - description = <<-EOT - Limit `id` to this many characters (minimum 6). - Set to `0` for unlimited length. - Set to `null` for keep the existing setting, which defaults to `0`. - Does not affect `id_full`. - EOT - validation { - condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 - error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." - } -} - -variable "label_key_case" { - type = string - default = null - description = <<-EOT - Controls the letter case of the `tags` keys (label names) for tags generated by this module. - Does not affect keys of tags passed in via the `tags` input. - Possible values: `lower`, `title`, `upper`. - Default value: `title`. - EOT - - validation { - condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) - error_message = "Allowed values: `lower`, `title`, `upper`." - } -} - -variable "label_value_case" { - type = string - default = null - description = <<-EOT - Controls the letter case of ID elements (labels) as included in `id`, - set as tag values, and output by this module individually. - Does not affect values of tags passed in via the `tags` input. - Possible values: `lower`, `title`, `upper` and `none` (no transformation). - Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. - Default value: `lower`. - EOT - - validation { - condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) - error_message = "Allowed values: `lower`, `title`, `upper`, `none`." - } -} - -variable "descriptor_formats" { - type = any - default = {} - description = <<-EOT - Describe additional descriptors to be output in the `descriptors` output map. - Map of maps. Keys are names of descriptors. Values are maps of the form - `{ - format = string - labels = list(string) - }` - (Type is `any` so the map values can later be enhanced to provide additional options.) - `format` is a Terraform format string to be passed to the `format()` function. - `labels` is a list of labels, in order, to pass to `format()` function. - Label values will be normalized before being passed to `format()` so they will be - identical to how they appear in `id`. - Default is `{}` (`descriptors` output will be empty). - EOT -} - -#### End of copy of cloudposse/terraform-null-label/variables.tf From 7d37c1e890514479fae404d13841a2754be70cbf Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 21:23:20 -0500 Subject: [PATCH 36/47] Add `atmos describe affected` command --- .../components/terraform/infra/vpc/context.tf | 279 ++++++++++++++++++ 1 file changed, 279 insertions(+) create mode 100644 examples/complete/components/terraform/infra/vpc/context.tf diff --git a/examples/complete/components/terraform/infra/vpc/context.tf b/examples/complete/components/terraform/infra/vpc/context.tf new file mode 100644 index 000000000..5e0ef8856 --- /dev/null +++ b/examples/complete/components/terraform/infra/vpc/context.tf @@ -0,0 +1,279 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "cloudposse/label/null" + version = "0.25.0" # requires Terraform >= 0.13.0 + + enabled = var.enabled + namespace = var.namespace + tenant = var.tenant + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + label_key_case = var.label_key_case + label_value_case = var.label_value_case + descriptor_formats = var.descriptor_formats + labels_as_tags = var.labels_as_tags + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = any + default = { + enabled = true + namespace = null + tenant = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + label_key_case = null + label_value_case = null + descriptor_formats = {} + # Note: we have to use [] instead of null for unset lists due to + # https://github.com/hashicorp/terraform/issues/28137 + # which was not fixed until Terraform 1.0.0, + # but we want the default to be all the labels in `label_order` + # and we want users to be able to prevent all tag generation + # by setting `labels_as_tags` to `[]`, so we need + # a different sentinel to indicate "default" + labels_as_tags = ["unset"] + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT + + validation { + condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`." + } + + validation { + condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" +} + +variable "tenant" { + type = string + default = null + description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" +} + +variable "environment" { + type = string + default = null + description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = <<-EOT + ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. + This is the only ID element not also included as a `tag`. + The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. + EOT +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between ID elements. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = <<-EOT + ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, + in the order they appear in the list. New attributes are appended to the + end of the list. The elements of the list are joined by the `delimiter` + and treated as a single ID element. + EOT +} + +variable "labels_as_tags" { + type = set(string) + default = ["default"] + description = <<-EOT + Set of labels (ID elements) to include as tags in the `tags` output. + Default is to include all labels. + Tags with empty values will not be included in the `tags` output. + Set to `[]` to suppress all generated tags. + **Notes:** + The value of the `name` tag, if included, will be the `id`, not the `name`. + Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be + changed in later chained modules. Attempts to change it will be silently ignored. + EOT +} + +variable "tags" { + type = map(string) + default = {} + description = <<-EOT + Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). + Neither the tag keys nor the tag values will be modified by this module. + EOT +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = <<-EOT + Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. + This is for some rare cases where resources want additional configuration of tags + and therefore take a list of maps with tag key, value, and additional configuration. + EOT +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The order in which the labels (ID elements) appear in the `id`. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Terraform regular expression (regex) string. + Characters matching the regex will be removed from the ID elements. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters (minimum 6). + Set to `0` for unlimited length. + Set to `null` for keep the existing setting, which defaults to `0`. + Does not affect `id_full`. + EOT + validation { + condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 + error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." + } +} + +variable "label_key_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of the `tags` keys (label names) for tags generated by this module. + Does not affect keys of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper`. + Default value: `title`. + EOT + + validation { + condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) + error_message = "Allowed values: `lower`, `title`, `upper`." + } +} + +variable "label_value_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of ID elements (labels) as included in `id`, + set as tag values, and output by this module individually. + Does not affect values of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper` and `none` (no transformation). + Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. + Default value: `lower`. + EOT + + validation { + condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "descriptor_formats" { + type = any + default = {} + description = <<-EOT + Describe additional descriptors to be output in the `descriptors` output map. + Map of maps. Keys are names of descriptors. Values are maps of the form + `{ + format = string + labels = list(string) + }` + (Type is `any` so the map values can later be enhanced to provide additional options.) + `format` is a Terraform format string to be passed to the `format()` function. + `labels` is a list of labels, in order, to pass to `format()` function. + Label values will be normalized before being passed to `format()` so they will be + identical to how they appear in `id`. + Default is `{}` (`descriptors` output will be empty). + EOT +} + +#### End of copy of cloudposse/terraform-null-label/variables.tf From 26ff11b76c48256dbe057f80583025a19f380943 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 22:19:15 -0500 Subject: [PATCH 37/47] Add `atmos describe affected` command --- .../components/terraform/infra/vpc/main.tf | 1 - internal/exec/describe_affected.go | 124 +++++++++++++----- pkg/config/schema.go | 8 +- pkg/utils/file_utils.go | 11 ++ 4 files changed, 105 insertions(+), 39 deletions(-) diff --git a/examples/complete/components/terraform/infra/vpc/main.tf b/examples/complete/components/terraform/infra/vpc/main.tf index a963adaff..c863b6193 100644 --- a/examples/complete/components/terraform/infra/vpc/main.tf +++ b/examples/complete/components/terraform/infra/vpc/main.tf @@ -62,4 +62,3 @@ module "subnets" { context = module.this.context } - diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index e4bc60cf9..a804a5edc 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -253,6 +253,7 @@ func ExecuteDescribeAffected( return nil, err } + // Find a slice of Patch objects with all the changes between the local and remote trees patch, err := localTree.Patch(remoteTree) u.PrintInfoVerbose(verbose, "\nChanged files:") @@ -262,12 +263,18 @@ func ExecuteDescribeAffected( changedFiles = append(changedFiles, fileStat.Name) } - affected := findAffected(currentStacks, remoteStacks) + 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) []cfg.Affected { +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 { @@ -286,10 +293,23 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c // Check `metadata` section if !isEqual(remoteStacks, stackName, "terraform", componentName, metadataSection, "metadata") { affected := cfg.Affected{ - ComponentType: "terraform", - Component: componentName, - Stack: stackName, - AffectedSection: "metadata", + ComponentType: "terraform", + Component: componentName, + Stack: stackName, + Affected: "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: "terraform", } res = append(res, affected) continue @@ -299,10 +319,10 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c 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, - AffectedSection: "vars", + ComponentType: "terraform", + Component: componentName, + Stack: stackName, + Affected: "vars", } res = append(res, affected) continue @@ -312,10 +332,10 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c 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, - AffectedSection: "env", + ComponentType: "terraform", + Component: componentName, + Stack: stackName, + Affected: "env", } res = append(res, affected) continue @@ -325,10 +345,10 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c 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, - AffectedSection: "settings", + ComponentType: "terraform", + Component: componentName, + Stack: stackName, + Affected: "settings", } res = append(res, affected) continue @@ -350,10 +370,23 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c // Check `metadata` section if !isEqual(remoteStacks, stackName, "helmfile", componentName, metadataSection, "metadata") { affected := cfg.Affected{ - ComponentType: "helmfile", - Component: componentName, - Stack: stackName, - AffectedSection: "metadata", + ComponentType: "helmfile", + Component: componentName, + Stack: stackName, + Affected: "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: "helmfile", } res = append(res, affected) continue @@ -363,10 +396,10 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c 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, - AffectedSection: "vars", + ComponentType: "helmfile", + Component: componentName, + Stack: stackName, + Affected: "vars", } res = append(res, affected) continue @@ -376,10 +409,10 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c 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, - AffectedSection: "env", + ComponentType: "helmfile", + Component: componentName, + Stack: stackName, + Affected: "env", } res = append(res, affected) continue @@ -389,10 +422,10 @@ func findAffected(currentStacks map[string]any, remoteStacks map[string]any) []c 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, - AffectedSection: "settings", + ComponentType: "helmfile", + Component: componentName, + Stack: stackName, + Affected: "settings", } res = append(res, affected) continue @@ -433,3 +466,26 @@ func isEqual( } 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/pkg/config/schema.go b/pkg/config/schema.go index 6b6addc19..47be27bfa 100644 --- a/pkg/config/schema.go +++ b/pkg/config/schema.go @@ -331,8 +331,8 @@ 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"` - AffectedSection string `yaml:"affected_section" json:"affected_section" mapstructure:"affected_section"` + 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/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 +} From 5fc42b7a7e853e36375b6b1eb3f598a807773cef Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 22:47:11 -0500 Subject: [PATCH 38/47] Add `atmos describe affected` command --- pkg/describe/describe_affected_test.go | 2 +- .../commands/describe/describe-affected.md | 57 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/pkg/describe/describe_affected_test.go b/pkg/describe/describe_affected_test.go index 8fa78a53a..34caf4ecd 100644 --- a/pkg/describe/describe_affected_test.go +++ b/pkg/describe/describe_affected_test.go @@ -21,7 +21,7 @@ func TestDescribeAffected(t *testing.T) { // 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" + ref := "" sha := "" affected, err := e.ExecuteDescribeAffected(cliConfig, ref, sha, true) diff --git a/website/docs/cli/commands/describe/describe-affected.md b/website/docs/cli/commands/describe/describe-affected.md index 31c79290f..1d26854bc 100644 --- a/website/docs/cli/commands/describe/describe-affected.md +++ b/website/docs/cli/commands/describe/describe-affected.md @@ -36,6 +36,7 @@ Run `atmos describe affected --help` to see all the available options ```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 @@ -53,3 +54,59 @@ atmos describe affected --sha 3a5eafeab90426bd82bf5899896b28cc0bab3073 | `--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 | no | + +## Output + +The command outputs a list of objects (in JSON or YAML formats). + +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 affected Atmos component (`terraform` or `helmfile`) +- `affected` shows what was changed for the component. The possible values are: + + - `vars` - the `vars` component section in the stack config has been modified + - `env` - the `env` component section in the stack config has been modified + - `settings` - the `settings` component section in the stack config has been modified + - `metadata` - the `metadata` component section in the stack config has been modified + - `terraform` - the Terraform component (Terraform files) that the affected Atmos component provisions has been changed + - `helmfile` - the Helmfile component (Helmfile files) that the affected Atmos component provisions has been changed + +
+ +For example: + +```json +[ + { + "stack": "tenant2-ue2-staging", + "component_type": "terraform", + "component": "infra/vpc", + "affected": "terraform" + }, + { + "stack": "tenant1-ue2-prod", + "component_type": "terraform", + "component": "test/test-component-override-3", + "affected": "env" + }, + { + "stack": "tenant1-ue2-dev", + "component_type": "terraform", + "component": "test/test-component-override-3", + "affected": "vars" + } +] +``` From d9226b0aeb213e8c983e7ac47cfb15445fcf7036 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 23:44:47 -0500 Subject: [PATCH 39/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 29 ++++++++++++++++++++++++-- pkg/describe/describe_affected_test.go | 2 +- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index a804a5edc..32930b16e 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -233,9 +233,34 @@ func ExecuteDescribeAffected( u.PrintInfo(fmt.Sprintf("Remote repo HEAD: %s", remoteRepoHead)) } - localCommit, err := localRepo.CommitObject(localRepoHead.Hash()) + localSha := localRepoHead.Hash() + localCommit, err := localRepo.CommitObject(localSha) if err != nil { - return nil, err + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nNo local commits found. Checking out HEAD SHA: %s\n", localSha)) + + w, err := localRepo.Worktree() + if err != nil { + return nil, err + } + + checkoutOptions := git.CheckoutOptions{ + Hash: localSha, + Create: false, + Force: true, + Keep: false, + } + + err = w.Checkout(&checkoutOptions) + if err != nil { + return nil, err + } + + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out HEAD SHA: %s\n", localSha)) + + localCommit, err = localRepo.CommitObject(localSha) + if err != nil { + return nil, err + } } localTree, err := localCommit.Tree() diff --git a/pkg/describe/describe_affected_test.go b/pkg/describe/describe_affected_test.go index 34caf4ecd..8fa78a53a 100644 --- a/pkg/describe/describe_affected_test.go +++ b/pkg/describe/describe_affected_test.go @@ -21,7 +21,7 @@ func TestDescribeAffected(t *testing.T) { // Git reference and commit SHA // Refer to https://git-scm.com/book/en/v2/Git-Internals-Git-References for more details - ref := "" + ref := "refs/heads/master" sha := "" affected, err := e.ExecuteDescribeAffected(cliConfig, ref, sha, true) From 429d6f5160b8b28d787b1e4626ef067125cc1bb9 Mon Sep 17 00:00:00 2001 From: aknysh Date: Wed, 14 Dec 2022 23:59:56 -0500 Subject: [PATCH 40/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 32930b16e..08087a49b 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -233,10 +233,12 @@ func ExecuteDescribeAffected( u.PrintInfo(fmt.Sprintf("Remote repo HEAD: %s", remoteRepoHead)) } + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nGetting local repo commit object...")) + localSha := localRepoHead.Hash() localCommit, err := localRepo.CommitObject(localSha) if err != nil { - u.PrintInfoVerbose(verbose, fmt.Sprintf("\nNo local commits found. Checking out HEAD SHA: %s\n", localSha)) + u.PrintInfoVerbose(verbose, fmt.Sprintf("No local commits found. Checking out HEAD SHA: %s\n", localSha)) w, err := localRepo.Worktree() if err != nil { @@ -255,7 +257,7 @@ func ExecuteDescribeAffected( return nil, err } - u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out HEAD SHA: %s\n", localSha)) + u.PrintInfoVerbose(verbose, fmt.Sprintf("Checked out HEAD SHA: %s\n", localSha)) localCommit, err = localRepo.CommitObject(localSha) if err != nil { @@ -263,25 +265,42 @@ func ExecuteDescribeAffected( } } + u.PrintInfoVerbose(verbose, fmt.Sprintf("Got local repo commit object")) + u.PrintInfoVerbose(verbose, fmt.Sprintf("Getting local repo commit tree...")) + localTree, err := localCommit.Tree() if err != nil { return nil, err } + u.PrintInfoVerbose(verbose, fmt.Sprintf("Got local repo commit tree")) + u.PrintInfoVerbose(verbose, fmt.Sprintf("Getting remote repo commit object...")) + remoteCommit, err := localRepo.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("Getting diff between the local and remote repos...")) + // Find a slice of Patch objects with all the changes between the local and remote trees patch, err := localTree.Patch(remoteTree) + if err != nil { + return nil, err + } + u.PrintInfoVerbose(verbose, fmt.Sprintf("Got diff between the local and remote repos")) u.PrintInfoVerbose(verbose, "\nChanged files:") + var changedFiles []string for _, fileStat := range patch.Stats() { u.PrintMessageVerbose(verbose && fileStat.Name != "", fileStat.Name) From 41cf866d531102ee62b0c8904c6e0c1e317aa9f8 Mon Sep 17 00:00:00 2001 From: aknysh Date: Thu, 15 Dec 2022 00:15:43 -0500 Subject: [PATCH 41/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 08087a49b..38c66c4e0 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -276,7 +276,7 @@ func ExecuteDescribeAffected( u.PrintInfoVerbose(verbose, fmt.Sprintf("Got local repo commit tree")) u.PrintInfoVerbose(verbose, fmt.Sprintf("Getting remote repo commit object...")) - remoteCommit, err := localRepo.CommitObject(remoteRepoHead.Hash()) + remoteCommit, err := remoteRepo.CommitObject(remoteRepoHead.Hash()) if err != nil { return nil, err } @@ -290,7 +290,7 @@ func ExecuteDescribeAffected( } u.PrintInfoVerbose(verbose, fmt.Sprintf("Got remote repo commit tree")) - u.PrintInfoVerbose(verbose, fmt.Sprintf("Getting diff between the local and remote repos...")) + u.PrintInfoVerbose(verbose, fmt.Sprintf("Finding diff between the local and remote repos...")) // Find a slice of Patch objects with all the changes between the local and remote trees patch, err := localTree.Patch(remoteTree) @@ -298,7 +298,7 @@ func ExecuteDescribeAffected( return nil, err } - u.PrintInfoVerbose(verbose, fmt.Sprintf("Got diff between the local and remote repos")) + u.PrintInfoVerbose(verbose, fmt.Sprintf("Found diff between the local and remote repos")) u.PrintInfoVerbose(verbose, "\nChanged files:") var changedFiles []string From 5023796ea17173ba80ce017fd29b609f1687ae25 Mon Sep 17 00:00:00 2001 From: aknysh Date: Thu, 15 Dec 2022 00:27:29 -0500 Subject: [PATCH 42/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 33 ++++---------------------- pkg/describe/describe_affected_test.go | 6 +++-- 2 files changed, 8 insertions(+), 31 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 38c66c4e0..e17a06b2f 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -235,34 +235,9 @@ func ExecuteDescribeAffected( u.PrintInfoVerbose(verbose, fmt.Sprintf("\nGetting local repo commit object...")) - localSha := localRepoHead.Hash() - localCommit, err := localRepo.CommitObject(localSha) + localCommit, err := localRepo.CommitObject(localRepoHead.Hash()) if err != nil { - u.PrintInfoVerbose(verbose, fmt.Sprintf("No local commits found. Checking out HEAD SHA: %s\n", localSha)) - - w, err := localRepo.Worktree() - if err != nil { - return nil, err - } - - checkoutOptions := git.CheckoutOptions{ - Hash: localSha, - Create: false, - Force: true, - Keep: false, - } - - err = w.Checkout(&checkoutOptions) - if err != nil { - return nil, err - } - - u.PrintInfoVerbose(verbose, fmt.Sprintf("Checked out HEAD SHA: %s\n", localSha)) - - localCommit, err = localRepo.CommitObject(localSha) - if err != nil { - return nil, err - } + return nil, err } u.PrintInfoVerbose(verbose, fmt.Sprintf("Got local repo commit object")) @@ -290,7 +265,7 @@ func ExecuteDescribeAffected( } u.PrintInfoVerbose(verbose, fmt.Sprintf("Got remote repo commit tree")) - u.PrintInfoVerbose(verbose, fmt.Sprintf("Finding diff between the local and remote repos...")) + u.PrintInfoVerbose(verbose, fmt.Sprintf("Finding diff between the local and remote commits...")) // Find a slice of Patch objects with all the changes between the local and remote trees patch, err := localTree.Patch(remoteTree) @@ -298,7 +273,7 @@ func ExecuteDescribeAffected( return nil, err } - u.PrintInfoVerbose(verbose, fmt.Sprintf("Found diff between the local and remote repos")) + u.PrintInfoVerbose(verbose, fmt.Sprintf("Found diff between the local and remote commits")) u.PrintInfoVerbose(verbose, "\nChanged files:") var changedFiles []string diff --git a/pkg/describe/describe_affected_test.go b/pkg/describe/describe_affected_test.go index 8fa78a53a..09200fbde 100644 --- a/pkg/describe/describe_affected_test.go +++ b/pkg/describe/describe_affected_test.go @@ -1,6 +1,7 @@ package describe import ( + "fmt" e "github.com/cloudposse/atmos/internal/exec" cfg "github.com/cloudposse/atmos/pkg/config" "github.com/stretchr/testify/assert" @@ -27,7 +28,8 @@ func TestDescribeAffected(t *testing.T) { affected, err := e.ExecuteDescribeAffected(cliConfig, ref, sha, true) assert.Nil(t, err) - componentSectionYaml, err := yaml.Marshal(affected) + affectedYaml, err := yaml.Marshal(affected) assert.Nil(t, err) - t.Log(string(componentSectionYaml)) + + t.Log(fmt.Sprintf("\nAffected components and stacks:\n%v", string(affectedYaml))) } From e3f4a8950e3524599ec927d471c283d4e4d74662 Mon Sep 17 00:00:00 2001 From: Andriy Knysh Date: Thu, 15 Dec 2022 08:42:48 -0500 Subject: [PATCH 43/47] Update website/docs/cli/commands/describe/describe-affected.md Co-authored-by: Erik Osterman (CEO @ Cloud Posse) --- website/docs/cli/commands/describe/describe-affected.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/cli/commands/describe/describe-affected.md b/website/docs/cli/commands/describe/describe-affected.md index 1d26854bc..27e649c89 100644 --- a/website/docs/cli/commands/describe/describe-affected.md +++ b/website/docs/cli/commands/describe/describe-affected.md @@ -17,7 +17,7 @@ For the first commit, the command assumes that the repo root is a Git checkout. The second commit is specified on the command line by using the `--ref` or `--sha` flags. -If the flags are not provided, it will clone the HEAD of the default branch. +If the flags are not provided, the `ref` will be the default branch (e.g. `main`) and the `sha` will point to the `HEAD` of the branch. ::: ## Usage From 20b89ae7c00d66aa1cca89f3f81464d760d8bb93 Mon Sep 17 00:00:00 2001 From: aknysh Date: Thu, 15 Dec 2022 08:56:29 -0500 Subject: [PATCH 44/47] Add `atmos describe affected` command --- cmd/describe_affected.go | 4 ++-- internal/exec/describe_affected.go | 20 ++++++++-------- .../commands/describe/describe-affected.md | 23 +++++++++---------- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/cmd/describe_affected.go b/cmd/describe_affected.go index e037ddbe2..1f611079f 100644 --- a/cmd/describe_affected.go +++ b/cmd/describe_affected.go @@ -27,8 +27,8 @@ func init() { 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 --ref refs/heads/main --format=json|yaml ('json' is default)") - describeAffectedCmd.PersistentFlags().Bool("verbose", false, "atmos describe affected --ref refs/heads/main --verbose=true") + 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/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index e17a06b2f..0ccfe5454 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -315,7 +315,7 @@ func findAffected( ComponentType: "terraform", Component: componentName, Stack: stackName, - Affected: "metadata", + Affected: "stack.metadata", } res = append(res, affected) continue @@ -328,7 +328,7 @@ func findAffected( ComponentType: "terraform", Component: componentName, Stack: stackName, - Affected: "terraform", + Affected: "component", } res = append(res, affected) continue @@ -341,7 +341,7 @@ func findAffected( ComponentType: "terraform", Component: componentName, Stack: stackName, - Affected: "vars", + Affected: "stack.vars", } res = append(res, affected) continue @@ -354,7 +354,7 @@ func findAffected( ComponentType: "terraform", Component: componentName, Stack: stackName, - Affected: "env", + Affected: "stack.env", } res = append(res, affected) continue @@ -367,7 +367,7 @@ func findAffected( ComponentType: "terraform", Component: componentName, Stack: stackName, - Affected: "settings", + Affected: "stack.settings", } res = append(res, affected) continue @@ -392,7 +392,7 @@ func findAffected( ComponentType: "helmfile", Component: componentName, Stack: stackName, - Affected: "metadata", + Affected: "stack.metadata", } res = append(res, affected) continue @@ -405,7 +405,7 @@ func findAffected( ComponentType: "helmfile", Component: componentName, Stack: stackName, - Affected: "helmfile", + Affected: "component", } res = append(res, affected) continue @@ -418,7 +418,7 @@ func findAffected( ComponentType: "helmfile", Component: componentName, Stack: stackName, - Affected: "vars", + Affected: "stack.vars", } res = append(res, affected) continue @@ -431,7 +431,7 @@ func findAffected( ComponentType: "helmfile", Component: componentName, Stack: stackName, - Affected: "env", + Affected: "stack.env", } res = append(res, affected) continue @@ -444,7 +444,7 @@ func findAffected( ComponentType: "helmfile", Component: componentName, Stack: stackName, - Affected: "settings", + Affected: "stack.settings", } res = append(res, affected) continue diff --git a/website/docs/cli/commands/describe/describe-affected.md b/website/docs/cli/commands/describe/describe-affected.md index 27e649c89..fa48b231d 100644 --- a/website/docs/cli/commands/describe/describe-affected.md +++ b/website/docs/cli/commands/describe/describe-affected.md @@ -15,9 +15,9 @@ Use this command to show a list of the affected Atmos components and stacks give :::info For the first commit, the command assumes that the repo root is a Git checkout. -The second commit is specified on the command line by using the `--ref` or `--sha` flags. +The second commit is specified on the command line by using the `--ref` (Git Reference) or `--sha` (commit SHA) flags. -If the flags are not provided, the `ref` will be the default branch (e.g. `main`) and the `sha` will point to the `HEAD` of the branch. +If the flags are not provided, the `ref` will be the default branch (e.g. `main`) and the commit SHA will point to the `HEAD` of the branch. ::: ## Usage @@ -74,15 +74,14 @@ where: - `stack` is the affected Atmos stack - `component` is the affected Atmos component in the stack -- `component_type` is the type of the affected Atmos component (`terraform` or `helmfile`) +- `component_type` is the type of the component (`terraform` or `helmfile`) - `affected` shows what was changed for the component. The possible values are: - - `vars` - the `vars` component section in the stack config has been modified - - `env` - the `env` component section in the stack config has been modified - - `settings` - the `settings` component section in the stack config has been modified - - `metadata` - the `metadata` component section in the stack config has been modified - - `terraform` - the Terraform component (Terraform files) that the affected Atmos component provisions has been changed - - `helmfile` - the Helmfile component (Helmfile files) that the affected Atmos component provisions has been changed + - `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 (Terraform/Helmfile files) that the affected Atmos component provisions has been changed
@@ -94,19 +93,19 @@ For example: "stack": "tenant2-ue2-staging", "component_type": "terraform", "component": "infra/vpc", - "affected": "terraform" + "affected": "component" }, { "stack": "tenant1-ue2-prod", "component_type": "terraform", "component": "test/test-component-override-3", - "affected": "env" + "affected": "stack.env" }, { "stack": "tenant1-ue2-dev", "component_type": "terraform", "component": "test/test-component-override-3", - "affected": "vars" + "affected": "stack.vars" } ] ``` From 8c7134e8ce8bec8bcf51509889cc3d8286439a68 Mon Sep 17 00:00:00 2001 From: aknysh Date: Thu, 15 Dec 2022 11:24:59 -0500 Subject: [PATCH 45/47] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 28 +++--- .../commands/describe/describe-affected.md | 91 ++++++++++++++++--- 2 files changed, 91 insertions(+), 28 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 0ccfe5454..9f04fe689 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -156,9 +156,9 @@ func ExecuteDescribeAffected( // 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)) + 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") + u.PrintInfoVerbose(verbose, "\nChecking out the HEAD of the default branch ...\n") } if verbose { @@ -176,14 +176,14 @@ func ExecuteDescribeAffected( } if ref != "" { - u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out Git ref: %s\n", 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())) + 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)) + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecking out commit SHA '%s' ...\n", sha)) w, err := remoteRepo.Worktree() if err != nil { @@ -202,7 +202,7 @@ func ExecuteDescribeAffected( return nil, err } - u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out commit SHA: %s\n", sha)) + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out commit SHA '%s'\n", sha)) } currentStacks, err := ExecuteDescribeStacks(cliConfig, "", nil, nil, nil) @@ -229,26 +229,26 @@ func ExecuteDescribeAffected( } if verbose { - u.PrintInfo(fmt.Sprintf("Local repo HEAD: %s", localRepoHead)) + 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 local repo commit object...")) + 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 local repo commit object")) - u.PrintInfoVerbose(verbose, fmt.Sprintf("Getting local repo commit tree...")) + 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 local repo commit tree")) + 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()) @@ -265,15 +265,15 @@ func ExecuteDescribeAffected( } u.PrintInfoVerbose(verbose, fmt.Sprintf("Got remote repo commit tree")) - u.PrintInfoVerbose(verbose, fmt.Sprintf("Finding diff between the local and remote commits...")) + 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 local and remote trees + // 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 local and remote commits")) + u.PrintInfoVerbose(verbose, fmt.Sprintf("Found diff between the current working branch and remote branch")) u.PrintInfoVerbose(verbose, "\nChanged files:") var changedFiles []string diff --git a/website/docs/cli/commands/describe/describe-affected.md b/website/docs/cli/commands/describe/describe-affected.md index fa48b231d..68d8acd34 100644 --- a/website/docs/cli/commands/describe/describe-affected.md +++ b/website/docs/cli/commands/describe/describe-affected.md @@ -10,15 +10,78 @@ description: This command produces a list of the affected Atmos components and s 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 +
-:::info -For the first commit, the command assumes that the repo root is a Git checkout. +```shell +> atmos describe affected --verbose=true -The second commit is specified on the command line by using the `--ref` (Git Reference) or `--sha` (commit SHA) flags. +Cloning repo 'https://github.com/cloudposse/atmos' into the temp dir '/var/folders/g5/lbvzy_ld2hx4mgrgyp19bvb00000gn/T/16710736261366892599' -If the flags are not provided, the `ref` will be the default branch (e.g. `main`) and the commit SHA will point to the `HEAD` of the branch. -::: +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 @@ -47,17 +110,17 @@ atmos describe affected --sha 3a5eafeab90426bd82bf5899896b28cc0bab3073 ## Flags -| Flag | Description | Required | -|:------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------| -| `--ref` | Git reference with which to compare the current branch. Refer to [Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References) for more details | no | -| `--sha` | Git commit SHA with which to compare the current 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 | no | +| 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 formats). +The command outputs a list of objects (in JSON or YAML format). Each object has the following schema: @@ -81,7 +144,7 @@ where: - `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 (Terraform/Helmfile files) that the affected Atmos component provisions has been changed + - `component` - the Terraform or Helmfile component that the Atmos component provisions has been changed
From 93424c7510aacd9b2d02d09b5ceb7c778fc363e2 Mon Sep 17 00:00:00 2001 From: Andriy Knysh Date: Thu, 15 Dec 2022 12:41:30 -0500 Subject: [PATCH 46/47] Update website/docs/cli/commands/describe/describe-affected.md Co-authored-by: Erik Osterman (CEO @ Cloud Posse) --- website/docs/cli/commands/describe/describe-affected.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/docs/cli/commands/describe/describe-affected.md b/website/docs/cli/commands/describe/describe-affected.md index 68d8acd34..3dd819068 100644 --- a/website/docs/cli/commands/describe/describe-affected.md +++ b/website/docs/cli/commands/describe/describe-affected.md @@ -34,6 +34,8 @@ The command works by: - 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 stacks as affected. Atmos will then skip evaluating those stacks for differences since we already know that they are affected. +
```shell From d0710a24324aae1b908687212f393a48e4b96b47 Mon Sep 17 00:00:00 2001 From: aknysh Date: Thu, 15 Dec 2022 12:45:06 -0500 Subject: [PATCH 47/47] Add `atmos describe affected` command --- website/docs/cli/commands/describe/describe-affected.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/docs/cli/commands/describe/describe-affected.md b/website/docs/cli/commands/describe/describe-affected.md index 3dd819068..f9c00930a 100644 --- a/website/docs/cli/commands/describe/describe-affected.md +++ b/website/docs/cli/commands/describe/describe-affected.md @@ -34,7 +34,8 @@ The command works by: - 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 stacks as affected. Atmos will then skip evaluating those stacks for differences since we already know that they are 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.