diff --git a/adr/0004-tui.md b/adr/0004-tui.md new file mode 100644 index 00000000..cdf3502b --- /dev/null +++ b/adr/0004-tui.md @@ -0,0 +1,21 @@ +# 3. Terminal User Interface (TUI) + +Date: 22 March 2024 + +## Status +Accepted + +## Context +- Today, UDS CLI leverages the `pterm` library and `messaging` pkg in Zarf to provide a terminal user interface (TUI) for users. The TUI is used to display progress bars, tables, etc to the user. The current implementation of the TUI is tightly coupled with Zarf, making it difficult to customize and address the unique needs of UDS CLI. + + +- The UDS CLI team has formed the following hypothesis about UDS CLI users: UDS CLI users (particularly those doing `uds deploy`) are more interested in the status of their deployment than the details of the deployment process. + + +- In an effort to address the unique needs of UDS CLI users, the UDS CLI team would like to decouple UDS CLI from the Zarf TUI in an effort to make a custom user experience for UDS CLI users. + +## Decision +The UDS CLI team has decided to refactor the existing TUI implementation with [BubbleTea](https://github.com/charmbracelet/bubbletea) and other tools from the [Charm](https://charm.sh/) stack. We believe the Charm stack offers the most advanced and modern tooling for building TUIs in Go. + +## Consequences +This refactor is large and will be implemented one `uds` operation at time, starting with operations most likely to be performed during and after bundle installation. diff --git a/go.mod b/go.mod index 0b19b502..f63abb43 100644 --- a/go.mod +++ b/go.mod @@ -2,11 +2,19 @@ module github.com/defenseunicorns/uds-cli go 1.21.6 +replace github.com/defenseunicorns/zarf v0.32.5 => github.com/defenseunicorns/zarf v0.32.6-0.20240321202634-329a1ae1f69c + +replace github.com/defenseunicorns/maru-runner v0.0.2 => github.com/defenseunicorns/maru-runner v0.0.3-0.20240322171619-a7974e34d1d0 + require ( github.com/AlecAivazis/survey/v2 v2.3.7 github.com/alecthomas/jsonschema v0.0.0-20220216202328-9eeeec9d044b + github.com/charmbracelet/bubbles v0.16.1 + github.com/charmbracelet/bubbletea v0.25.0 + github.com/charmbracelet/lipgloss v0.9.1 github.com/defenseunicorns/maru-runner v0.0.2 github.com/defenseunicorns/zarf v0.32.5 + github.com/fatih/color v1.16.0 github.com/fsnotify/fsnotify v1.7.0 github.com/goccy/go-yaml v1.11.3 github.com/mholt/archiver/v3 v3.5.1 @@ -19,6 +27,7 @@ require ( golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81 golang.org/x/mod v0.16.0 golang.org/x/sync v0.6.0 + golang.org/x/term v0.18.0 helm.sh/helm/v3 v3.14.3 oras.land/oras-go/v2 v2.4.0 ) @@ -27,12 +36,12 @@ require ( atomicgo.dev/cursor v0.2.0 // indirect atomicgo.dev/keyboard v0.2.9 // indirect atomicgo.dev/schedule v0.1.0 // indirect - cloud.google.com/go v0.111.0 // indirect - cloud.google.com/go/compute v1.23.3 // indirect + cloud.google.com/go v0.112.1 // indirect + cloud.google.com/go/compute v1.24.0 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.5 // indirect - cloud.google.com/go/kms v1.15.5 // indirect - cloud.google.com/go/storage v1.35.1 // indirect + cloud.google.com/go/iam v1.1.6 // indirect + cloud.google.com/go/kms v1.15.7 // indirect + cloud.google.com/go/storage v1.38.0 // indirect cuelabs.dev/go/oci/ociregistry v0.0.0-20231103182354-93e78c079a13 // indirect cuelang.org/go v0.7.0 // indirect dario.cat/mergo v1.0.0 // indirect @@ -138,10 +147,7 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect - github.com/charmbracelet/bubbles v0.16.1 // indirect - github.com/charmbracelet/bubbletea v0.25.0 // indirect github.com/charmbracelet/harmonica v0.2.0 // indirect - github.com/charmbracelet/lipgloss v0.9.1 // indirect github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/cloudflare/circl v1.3.7 // indirect @@ -191,7 +197,6 @@ require ( github.com/facebookincubator/nvdtools v0.1.5 // indirect github.com/fairwindsops/pluto/v5 v5.18.4 // indirect github.com/fatih/camelcase v1.0.0 // indirect - github.com/fatih/color v1.16.0 // indirect github.com/felixge/fgprof v0.9.3 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fluxcd/helm-controller/api v0.37.4 // indirect @@ -250,7 +255,7 @@ require ( github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/googleapis/gax-go/v2 v2.12.1 // indirect github.com/gookit/color v1.5.4 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect @@ -445,12 +450,12 @@ require ( go.mongodb.org/mongo-driver v1.13.1 // indirect go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect - go.opentelemetry.io/otel v1.22.0 // indirect - go.opentelemetry.io/otel/metric v1.22.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 // indirect + go.opentelemetry.io/otel v1.23.0 // indirect + go.opentelemetry.io/otel/metric v1.23.0 // indirect go.opentelemetry.io/otel/sdk v1.22.0 // indirect - go.opentelemetry.io/otel/trace v1.22.0 // indirect + go.opentelemetry.io/otel/trace v1.23.0 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.step.sm/crypto v0.42.1 // indirect go.uber.org/multierr v1.11.0 // indirect @@ -458,20 +463,19 @@ require ( go4.org v0.0.0-20200411211856-f5505b9728dd // indirect golang.org/x/crypto v0.21.0 // indirect golang.org/x/net v0.22.0 // indirect - golang.org/x/oauth2 v0.16.0 // indirect + golang.org/x/oauth2 v0.17.0 // indirect golang.org/x/sys v0.18.0 // indirect - golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.19.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect - google.golang.org/api v0.159.0 // indirect + google.golang.org/api v0.166.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect - google.golang.org/grpc v1.61.0 // indirect - google.golang.org/protobuf v1.32.0 // indirect + google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240221002015-b0ce06bbee7c // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c // indirect + google.golang.org/grpc v1.61.1 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/evanphx/json-patch.v5 v5.6.0 // indirect gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index 0e005c5c..6b15e28c 100644 --- a/go.sum +++ b/go.sum @@ -39,7 +39,6 @@ cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w9 cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU= cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= @@ -78,7 +77,6 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= @@ -121,10 +119,8 @@ cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y97 cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= -cloud.google.com/go/kms v1.15.5/go.mod h1:cU2H5jnp6G2TDpUGZyqTCoy1n16fbubHZjmVXSMtwDI= cloud.google.com/go/kms v1.15.7 h1:7caV9K3yIxvlQPAcaFffhlT7d1qpxjB1wHBtjWa13SM= cloud.google.com/go/kms v1.15.7/go.mod h1:ub54lbsa6tDkUwnu4W7Yt1aAIFLnspgh0kPGToDukeI= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= @@ -187,7 +183,6 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= cloud.google.com/go/storage v1.38.0 h1:Az68ZRGlnNTpIBbLjSMIV2BDcwwXYlRlQzis0llkpJg= cloud.google.com/go/storage v1.38.0/go.mod h1:tlUADB0mAb9BgYls9lq+8MGkfzOXuLrnHXlpHmvFJoY= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= @@ -603,12 +598,10 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/daviddengcn/go-colortext v1.0.0 h1:ANqDyC0ys6qCSvuEK7l3g5RaehL/Xck9EX8ATG8oKsE= github.com/daviddengcn/go-colortext v1.0.0/go.mod h1:zDqEI5NVUop5QPpVJUxE9UO10hRnmkD5G4Pmri9+m4c= -github.com/defenseunicorns/maru-runner v0.0.2/go.mod h1:3K+JeLpud+rb8vC+nPFaTNjhqW40++6qFKKVTBEEzQM= -github.com/defenseunicorns/maru-runner v0.0.3-0.20240318172058-b7493c2ffa00 h1:hGweEhcsSKNTfHF/UKOAkikd5y7tw/rtykH9YuQ8gZA= -github.com/defenseunicorns/maru-runner v0.0.3-0.20240318172058-b7493c2ffa00/go.mod h1:D4aOUUpBwxE3gXEfQysfpzR388MmXJLq1R71jwnE8RY= -github.com/defenseunicorns/zarf v0.32.5/go.mod h1:dDIYZdh4XGkI/A6EpZHEBzQaQjw0hSbxJs4MQFOSqLc= -github.com/defenseunicorns/zarf v0.32.6-0.20240318172435-c7edb53ddf28 h1:OU7i2/5gvdJCiPmgey3Mi00vWir7ITXEsgFUPEIbA9s= -github.com/defenseunicorns/zarf v0.32.6-0.20240318172435-c7edb53ddf28/go.mod h1:OdLoiJaWsX0u/6l/IZO1VBSVcJw7d+ZwDUI4pjc5aAc= +github.com/defenseunicorns/maru-runner v0.0.3-0.20240322171619-a7974e34d1d0 h1:HgtK7fLR1+3PeEgZlykkN40hfngrAZrY2Oc1gv3Enas= +github.com/defenseunicorns/maru-runner v0.0.3-0.20240322171619-a7974e34d1d0/go.mod h1:hyQyYIFMb1b284uVEIbhc9qySyVCDbYcjteniHuNKE0= +github.com/defenseunicorns/zarf v0.32.6-0.20240321202634-329a1ae1f69c h1:EtW8FLWEJ8ducXN7Y1Z7kAmLGuVeicMOSLknYcvV/Q8= +github.com/defenseunicorns/zarf v0.32.6-0.20240321202634-329a1ae1f69c/go.mod h1:EISjg8T4jZUgc1QAMkX/RNQ0PS4WegKcJDZwztvQ2Bw= github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da h1:ZOjWpVsFZ06eIhnh4mkaceTiVoktdU67+M7KDHJ268M= github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da/go.mod h1:B3tI9iGHi4imdLi4Asdha1Sc6feLMTfPLXh9IUYmysk= github.com/depcheck-test/depcheck-test v0.0.0-20220607135614-199033aaa936 h1:foGzavPWwtoyBvjWyKJYDYsyzy+23iBV7NKTwdk+LRY= @@ -993,7 +986,6 @@ github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99 github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/gax-go/v2 v2.12.1 h1:9F8GV9r9ztXyAi00gsMQHNoF51xPZm8uj1dpYt2ZETM= github.com/googleapis/gax-go/v2 v2.12.1/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= @@ -1739,25 +1731,20 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 h1:P+/g8GpuJGYbOp2tAdKrIPUX9JO02q8Q0YNlHolpibA= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 h1:doUP+ExOpH3spVTLS0FcWGLnQrPct/hD/bCPbDRUEAU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0/go.mod h1:rdENBZMT2OE6Ne/KLwpiXudnAsbdrdBaqBvTN8M8BgA= -go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= go.opentelemetry.io/otel v1.23.0 h1:Df0pqjqExIywbMCMTxkAwzjLZtRf+bBKLbUcpxO2C9E= go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ= -go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= go.opentelemetry.io/otel/metric v1.23.0 h1:pazkx7ss4LFVVYSxYew7L5I6qvLXHA0Ap2pwV+9Cnpo= go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= -go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= go.opentelemetry.io/otel/trace v1.23.0 h1:37Ik5Ib7xfYVb4V1UtnT97T1jI+AoIYkJyPkuL4iJgI= go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= @@ -1940,7 +1927,6 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -2224,7 +2210,6 @@ google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.159.0/go.mod h1:0mu0TpK33qnydLvWqbImq2b1eQ5FHRSDCBzAxX9ZHyw= google.golang.org/api v0.166.0 h1:6m4NUwrZYhAaVIHZWxaKjw1L1vNAjtMwORmKRyEEo24= google.golang.org/api v0.166.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -2341,13 +2326,10 @@ google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqw google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917/go.mod h1:pZqR+glSb11aJ+JQcczCvgf47+duRuzNSKqE8YAQnV0= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= -google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= google.golang.org/genproto/googleapis/api v0.0.0-20240221002015-b0ce06bbee7c h1:9g7erC9qu44ks7UK4gDNlnk4kOxZG707xKm4jVniy6o= google.golang.org/genproto/googleapis/api v0.0.0-20240221002015-b0ce06bbee7c/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c h1:NUsgEN92SQQqzfA+YtqYNqYmB3DMMYLlIwUZAQFVFbo= google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -2386,7 +2368,6 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= @@ -2405,7 +2386,6 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/src/cmd/root.go b/src/cmd/root.go index 2183d90d..754b44d6 100644 --- a/src/cmd/root.go +++ b/src/cmd/root.go @@ -13,8 +13,8 @@ import ( "github.com/defenseunicorns/uds-cli/src/pkg/utils" "github.com/defenseunicorns/uds-cli/src/types" "github.com/defenseunicorns/zarf/src/cmd/common" + zarfCommon "github.com/defenseunicorns/zarf/src/cmd/common" "github.com/defenseunicorns/zarf/src/pkg/message" - "github.com/defenseunicorns/zarf/src/pkg/utils/exec" "github.com/spf13/cobra" ) @@ -33,7 +33,7 @@ var rootCmd = &cobra.Command{ return } - exec.ExitOnInterrupt() + zarfCommon.ExitOnInterrupt() // Don't add the logo to the help command if cmd.Parent() == nil { diff --git a/src/cmd/uds.go b/src/cmd/uds.go index 5e078d5f..964861ef 100644 --- a/src/cmd/uds.go +++ b/src/cmd/uds.go @@ -20,7 +20,7 @@ import ( "github.com/defenseunicorns/uds-cli/src/pkg/bundle/tui/deploy" zarfConfig "github.com/defenseunicorns/zarf/src/config" "github.com/defenseunicorns/zarf/src/pkg/message" - zarfUtils "github.com/defenseunicorns/zarf/src/pkg/utils" + "github.com/defenseunicorns/zarf/src/pkg/utils/helpers" zarfTypes "github.com/defenseunicorns/zarf/src/types" goyaml "github.com/goccy/go-yaml" "github.com/spf13/cobra" @@ -35,7 +35,7 @@ var createCmd = &cobra.Command{ PreRun: func(_ *cobra.Command, args []string) { pathToBundleFile := "" if len(args) > 0 { - if !zarfUtils.IsDir(args[0]) { + if !helpers.IsDir(args[0]) { message.Fatalf(nil, "(%q) is not a valid path to a directory", args[0]) } pathToBundleFile = filepath.Join(args[0]) diff --git a/src/pkg/bundle/common.go b/src/pkg/bundle/common.go index 54fe6049..5130f356 100644 --- a/src/pkg/bundle/common.go +++ b/src/pkg/bundle/common.go @@ -244,7 +244,7 @@ func (b *Bundle) CalculateBuildInfo() error { // ValidateBundleSignature validates the bundle signature func ValidateBundleSignature(bundleYAMLPath, signaturePath, publicKeyPath string) error { - if zarfUtils.InvalidPath(bundleYAMLPath) { + if helpers.InvalidPath(bundleYAMLPath) { return fmt.Errorf("path for %s at %s does not exist", config.BundleYAML, bundleYAMLPath) } // The package is not signed, and no public key was provided @@ -252,11 +252,11 @@ func ValidateBundleSignature(bundleYAMLPath, signaturePath, publicKeyPath string return nil } // The package is not signed, but a public key was provided - if zarfUtils.InvalidPath(signaturePath) && !zarfUtils.InvalidPath(publicKeyPath) { + if helpers.InvalidPath(signaturePath) && !helpers.InvalidPath(publicKeyPath) { return fmt.Errorf("package is not signed, but a public key was provided") } // The package is signed, but no public key was provided - if !zarfUtils.InvalidPath(signaturePath) && zarfUtils.InvalidPath(publicKeyPath) { + if !helpers.InvalidPath(signaturePath) && helpers.InvalidPath(publicKeyPath) { return fmt.Errorf("package is signed, but no public key was provided") } diff --git a/src/pkg/bundle/pull.go b/src/pkg/bundle/pull.go index 41815746..54e16072 100644 --- a/src/pkg/bundle/pull.go +++ b/src/pkg/bundle/pull.go @@ -16,7 +16,6 @@ import ( zarfConfig "github.com/defenseunicorns/zarf/src/config" "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/oci" - "github.com/defenseunicorns/zarf/src/pkg/utils" "github.com/defenseunicorns/zarf/src/pkg/utils/helpers" "github.com/defenseunicorns/zarf/src/pkg/zoci" "github.com/mholt/archiver/v4" @@ -29,7 +28,7 @@ func (b *Bundle) Pull() error { // use uds-cache/packages as the dst dir for the pull to get auto caching // we use an ORAS ocistore to make that dir look like an OCI artifact cacheDir := filepath.Join(zarfConfig.GetAbsCachePath(), "packages") - if err := utils.CreateDirectory(cacheDir, 0o755); err != nil { + if err := helpers.CreateDirectory(cacheDir, 0o755); err != nil { return err } diff --git a/src/pkg/bundle/remote.go b/src/pkg/bundle/remote.go index 67a1c8f7..545ddd95 100644 --- a/src/pkg/bundle/remote.go +++ b/src/pkg/bundle/remote.go @@ -22,6 +22,7 @@ import ( "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/oci" zarfUtils "github.com/defenseunicorns/zarf/src/pkg/utils" + "github.com/defenseunicorns/zarf/src/pkg/utils/helpers" "github.com/defenseunicorns/zarf/src/pkg/zoci" goyaml "github.com/goccy/go-yaml" "github.com/mholt/archiver/v4" @@ -56,7 +57,7 @@ func (op *ociProvider) getBundleManifest() (*oci.Manifest, error) { // LoadBundleMetadata loads a remote bundle's metadata func (op *ociProvider) LoadBundleMetadata() (types.PathMap, error) { ctx := context.TODO() - if err := zarfUtils.CreateDirectory(filepath.Join(op.dst, config.BlobsDir), 0700); err != nil { + if err := helpers.CreateDirectory(filepath.Join(op.dst, config.BlobsDir), 0700); err != nil { return nil, err } diff --git a/src/pkg/bundle/tarball.go b/src/pkg/bundle/tarball.go index eb69a849..5fbbca57 100644 --- a/src/pkg/bundle/tarball.go +++ b/src/pkg/bundle/tarball.go @@ -18,6 +18,7 @@ import ( "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/oci" zarfUtils "github.com/defenseunicorns/zarf/src/pkg/utils" + "github.com/defenseunicorns/zarf/src/pkg/utils/helpers" "github.com/defenseunicorns/zarf/src/pkg/zoci" av3 "github.com/mholt/archiver/v3" av4 "github.com/mholt/archiver/v4" @@ -166,7 +167,7 @@ func (tp *tarballBundleProvider) loadBundleManifest() error { defer os.Remove(manifestPath) - if err := zarfUtils.SHAsMatch(manifestPath, bundleManifestDesc.Digest.Encoded()); err != nil { + if err := helpers.SHAsMatch(manifestPath, bundleManifestDesc.Digest.Encoded()); err != nil { return err } @@ -206,7 +207,7 @@ func (tp *tarballBundleProvider) LoadBundleMetadata() (types.PathMap, error) { pathInTarball := filepath.Join(config.BlobsDir, layer.Digest.Encoded()) abs := filepath.Join(tp.dst, pathInTarball) loaded[path] = abs - if !zarfUtils.InvalidPath(abs) && zarfUtils.SHAsMatch(abs, layer.Digest.Encoded()) == nil { + if !helpers.InvalidPath(abs) && helpers.SHAsMatch(abs, layer.Digest.Encoded()) == nil { continue } if err := av3.Extract(tp.src, pathInTarball, tp.dst); err != nil { diff --git a/src/pkg/bundler/fetcher/remote.go b/src/pkg/bundler/fetcher/remote.go index 56fffcaf..31a7873c 100644 --- a/src/pkg/bundler/fetcher/remote.go +++ b/src/pkg/bundler/fetcher/remote.go @@ -19,6 +19,7 @@ import ( "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/oci" zarfUtils "github.com/defenseunicorns/zarf/src/pkg/utils" + "github.com/defenseunicorns/zarf/src/pkg/utils/helpers" "github.com/defenseunicorns/zarf/src/pkg/zoci" zarfTypes "github.com/defenseunicorns/zarf/src/types" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -150,7 +151,7 @@ func (f *remoteFetcher) remoteToLocal(layersToCopy []ocispec.Descriptor) ([]ocis // Grab tmpDirSize and add it to the estimatedBytes, otherwise the progress bar will be off // because as multiple packages are pulled into the tmpDir, RenderProgressBarForLocalDirWrite continues to // add their size which results in strange MB ratios - tmpDirSize, err := zarfUtils.GetDirSize(f.cfg.TmpDstDir) + tmpDirSize, err := helpers.GetDirSize(f.cfg.TmpDstDir) if err != nil { return nil, err } diff --git a/src/pkg/sources/remote.go b/src/pkg/sources/remote.go index e3895eae..f23631ed 100644 --- a/src/pkg/sources/remote.go +++ b/src/pkg/sources/remote.go @@ -18,6 +18,7 @@ import ( "github.com/defenseunicorns/zarf/src/pkg/layout" "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/oci" + "github.com/defenseunicorns/zarf/src/pkg/packager/filters" "github.com/defenseunicorns/zarf/src/pkg/packager/sources" zarfUtils "github.com/defenseunicorns/zarf/src/pkg/utils" "github.com/defenseunicorns/zarf/src/pkg/zoci" @@ -39,16 +40,16 @@ type RemoteBundle struct { } // LoadPackage loads a Zarf package from a remote bundle -func (r *RemoteBundle) LoadPackage(dst *layout.PackagePaths, unarchiveAll bool) error { +func (r *RemoteBundle) LoadPackage(dst *layout.PackagePaths, _ filters.ComponentFilterStrategy, unarchiveAll bool) (zarfTypes.ZarfPackage, []string, error) { // todo: progress bar?? layers, err := r.downloadPkgFromRemoteBundle() if err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } var pkg zarfTypes.ZarfPackage if err = zarfUtils.ReadYaml(dst.ZarfYAML, &pkg); err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } // record number of components to be deployed for TUI @@ -59,7 +60,7 @@ func (r *RemoteBundle) LoadPackage(dst *layout.PackagePaths, unarchiveAll bool) err = sources.ValidatePackageIntegrity(dst, pkg.Metadata.AggregateChecksum, r.isPartial) if err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } if unarchiveAll { @@ -68,39 +69,39 @@ func (r *RemoteBundle) LoadPackage(dst *layout.PackagePaths, unarchiveAll bool) if layout.IsNotLoaded(err) { _, err := dst.Components.Create(component) if err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } } else { - return err + return zarfTypes.ZarfPackage{}, nil, err } } } if dst.SBOMs.Path != "" { if err := dst.SBOMs.Unarchive(); err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } } } - return nil + return pkg, nil, err } // LoadPackageMetadata loads a Zarf package's metadata from a remote bundle -func (r *RemoteBundle) LoadPackageMetadata(dst *layout.PackagePaths, _ bool, _ bool) (err error) { +func (r *RemoteBundle) LoadPackageMetadata(dst *layout.PackagePaths, _ bool, _ bool) (zarfTypes.ZarfPackage, []string, error) { ctx := context.TODO() root, err := r.Remote.FetchRoot(ctx) if err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } pkgManifestDesc := root.Locate(r.PkgManifestSHA) if oci.IsEmptyDescriptor(pkgManifestDesc) { - return fmt.Errorf("zarf package %s with manifest sha %s not found", r.PkgName, r.PkgManifestSHA) + return zarfTypes.ZarfPackage{}, nil, fmt.Errorf("zarf package %s with manifest sha %s not found", r.PkgName, r.PkgManifestSHA) } // look at Zarf pkg manifest, grab zarf.yaml desc and download it pkgManifest, err := r.Remote.FetchManifest(ctx, pkgManifestDesc) if err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } var zarfYAMLDesc ocispec.Descriptor @@ -110,17 +111,17 @@ func (r *RemoteBundle) LoadPackageMetadata(dst *layout.PackagePaths, _ bool, _ b break } } - zarfYAMLBytes, err := r.Remote.FetchLayer(ctx, zarfYAMLDesc) + pkgBytes, err := r.Remote.FetchLayer(ctx, zarfYAMLDesc) if err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } - var zarfYAML zarfTypes.ZarfPackage - if err = goyaml.Unmarshal(zarfYAMLBytes, &zarfYAML); err != nil { - return err + var pkg zarfTypes.ZarfPackage + if err = goyaml.Unmarshal(pkgBytes, &pkg); err != nil { + return zarfTypes.ZarfPackage{}, nil, err } - err = zarfUtils.WriteYaml(filepath.Join(dst.Base, config.ZarfYAML), zarfYAML, 0600) + err = zarfUtils.WriteYaml(filepath.Join(dst.Base, config.ZarfYAML), pkg, 0600) if err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } // grab checksums.txt so we can validate pkg integrity @@ -129,11 +130,11 @@ func (r *RemoteBundle) LoadPackageMetadata(dst *layout.PackagePaths, _ bool, _ b if layer.Annotations[ocispec.AnnotationTitle] == config.ChecksumsTxt { checksumBytes, err := r.Remote.FetchLayer(ctx, layer) if err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } err = os.WriteFile(filepath.Join(dst.Base, config.ChecksumsTxt), checksumBytes, 0600) if err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } checksumLayer = layer break @@ -142,8 +143,8 @@ func (r *RemoteBundle) LoadPackageMetadata(dst *layout.PackagePaths, _ bool, _ b dst.SetFromLayers([]ocispec.Descriptor{pkgManifestDesc, checksumLayer}) - err = sources.ValidatePackageIntegrity(dst, zarfYAML.Metadata.AggregateChecksum, true) - return err + err = sources.ValidatePackageIntegrity(dst, pkg.Metadata.AggregateChecksum, true) + return pkg, nil, err } // Collect doesn't need to be implemented diff --git a/src/pkg/sources/tarball.go b/src/pkg/sources/tarball.go index 0d0e1bdb..99079498 100644 --- a/src/pkg/sources/tarball.go +++ b/src/pkg/sources/tarball.go @@ -16,6 +16,7 @@ import ( "github.com/defenseunicorns/zarf/src/pkg/layout" "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/oci" + "github.com/defenseunicorns/zarf/src/pkg/packager/filters" "github.com/defenseunicorns/zarf/src/pkg/packager/sources" zarfUtils "github.com/defenseunicorns/zarf/src/pkg/utils" "github.com/defenseunicorns/zarf/src/pkg/utils/helpers" @@ -38,18 +39,18 @@ type TarballBundle struct { } // LoadPackage loads a Zarf package from a local tarball bundle -func (t *TarballBundle) LoadPackage(dst *layout.PackagePaths, unarchiveAll bool) error { +func (t *TarballBundle) LoadPackage(dst *layout.PackagePaths, _ filters.ComponentFilterStrategy, unarchiveAll bool) (zarfTypes.ZarfPackage, []string, error) { packageSpinner := message.NewProgressSpinner("Loading bundled Zarf package: %s", t.PkgName) defer packageSpinner.Stop() files, err := t.extractPkgFromBundle() if err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } var pkg zarfTypes.ZarfPackage if err = zarfUtils.ReadYaml(dst.ZarfYAML, &pkg); err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } dst.SetFromPaths(files) @@ -58,7 +59,7 @@ func (t *TarballBundle) LoadPackage(dst *layout.PackagePaths, unarchiveAll bool) deploy.Program.Send(fmt.Sprintf("totalComponents:%d", len(pkg.Components))) if err := sources.ValidatePackageIntegrity(dst, pkg.Metadata.AggregateChecksum, t.isPartial); err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } if unarchiveAll { @@ -67,26 +68,26 @@ func (t *TarballBundle) LoadPackage(dst *layout.PackagePaths, unarchiveAll bool) if layout.IsNotLoaded(err) { _, err := dst.Components.Create(component) if err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } } else { - return err + return zarfTypes.ZarfPackage{}, nil, err } } } if dst.SBOMs.Path != "" { if err := dst.SBOMs.Unarchive(); err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } } } packageSpinner.Successf("Loaded bundled Zarf package: %s", t.PkgName) - return nil + return pkg, nil, err } // LoadPackageMetadata loads a Zarf package's metadata from a local tarball bundle -func (t *TarballBundle) LoadPackageMetadata(dst *layout.PackagePaths, _ bool, _ bool) (err error) { +func (t *TarballBundle) LoadPackageMetadata(dst *layout.PackagePaths, _ bool, _ bool) (zarfTypes.ZarfPackage, []string, error) { ctx := context.TODO() format := av4.CompressedArchive{ Compression: av4.Zstd{}, @@ -95,12 +96,12 @@ func (t *TarballBundle) LoadPackageMetadata(dst *layout.PackagePaths, _ bool, _ sourceArchive, err := os.Open(t.BundleLocation) if err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } var imageManifest oci.Manifest if err := format.Extract(ctx, sourceArchive, []string{filepath.Join(config.BlobsDir, t.PkgManifestSHA)}, utils.ExtractJSON(&imageManifest)); err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } var zarfYamlSHA string @@ -112,7 +113,7 @@ func (t *TarballBundle) LoadPackageMetadata(dst *layout.PackagePaths, _ bool, _ } if zarfYamlSHA == "" { - return fmt.Errorf(fmt.Sprintf("zarf.yaml with SHA %s not found", zarfYamlSHA)) + return zarfTypes.ZarfPackage{}, nil, fmt.Errorf(fmt.Sprintf("zarf.yaml with SHA %s not found", zarfYamlSHA)) } // grab SHA of checksums.txt @@ -127,7 +128,7 @@ func (t *TarballBundle) LoadPackageMetadata(dst *layout.PackagePaths, _ bool, _ // reset file reader _, err = sourceArchive.Seek(0, 0) if err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } // grab zarf.yaml and checksums.txt @@ -157,25 +158,25 @@ func (t *TarballBundle) LoadPackageMetadata(dst *layout.PackagePaths, _ bool, _ }); err != nil { err = sourceArchive.Close() if err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } - return err + return zarfTypes.ZarfPackage{}, nil, err } // deserialize zarf.yaml to grab checksum for validating pkg integrity - var zarfYAML zarfTypes.ZarfPackage - err = zarfUtils.ReadYaml(dst.ZarfYAML, &zarfYAML) + var pkg zarfTypes.ZarfPackage + err = zarfUtils.ReadYaml(dst.ZarfYAML, &pkg) if err != nil { - return err + return zarfTypes.ZarfPackage{}, nil, err } dst.SetFromPaths(filePaths) - if err := sources.ValidatePackageIntegrity(dst, zarfYAML.Metadata.AggregateChecksum, true); err != nil { - return err + if err := sources.ValidatePackageIntegrity(dst, pkg.Metadata.AggregateChecksum, true); err != nil { + return zarfTypes.ZarfPackage{}, nil, err } err = sourceArchive.Close() - return err + return pkg, nil, err } // Collect doesn't need to be implemented @@ -229,7 +230,7 @@ func (t *TarballBundle) extractPkgFromBundle() ([]string, error) { } size := desc.Size layerDst := filepath.Join(t.TmpDir, cleanPath) - if err := zarfUtils.CreateDirectory(filepath.Dir(layerDst), 0700); err != nil { + if err := helpers.CreateDirectory(filepath.Dir(layerDst), 0700); err != nil { return err } diff --git a/src/pkg/utils/oci.go b/src/pkg/utils/oci.go index b8fff8bd..228861e5 100644 --- a/src/pkg/utils/oci.go +++ b/src/pkg/utils/oci.go @@ -18,6 +18,7 @@ import ( "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/oci" "github.com/defenseunicorns/zarf/src/pkg/zoci" + zarfTypes "github.com/defenseunicorns/zarf/src/types" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "oras.land/oras-go/v2" "oras.land/oras-go/v2/content" @@ -262,7 +263,11 @@ func EnsureOCIPrefix(source string) string { // GetZarfLayers grabs the necessary Zarf pkg layers from a remote OCI registry func GetZarfLayers(remote zoci.Remote, pkg types.Package, pkgRootManifest *oci.Manifest) ([]ocispec.Descriptor, error) { ctx := context.TODO() - layersFromComponents, err := remote.LayersFromRequestedComponents(ctx, pkg.OptionalComponents) + var optComponents []zarfTypes.ZarfComponent + for _, c := range pkg.OptionalComponents { + optComponents = append(optComponents, zarfTypes.ZarfComponent{Name: c}) + } + layersFromComponents, err := remote.LayersFromRequestedComponents(ctx, optComponents) if err != nil { return nil, err } diff --git a/src/pkg/utils/utils.go b/src/pkg/utils/utils.go index e8539ac3..6fec9d35 100644 --- a/src/pkg/utils/utils.go +++ b/src/pkg/utils/utils.go @@ -18,7 +18,7 @@ import ( "github.com/defenseunicorns/uds-cli/src/config" "github.com/defenseunicorns/uds-cli/src/types" "github.com/defenseunicorns/zarf/src/pkg/message" - "github.com/defenseunicorns/zarf/src/pkg/utils" + "github.com/defenseunicorns/zarf/src/pkg/utils/helpers" av4 "github.com/mholt/archiver/v4" "github.com/pterm/pterm" ) @@ -38,7 +38,7 @@ func GracefulPanic() { // IsValidTarballPath returns true if the path is a valid tarball path to a bundle tarball func IsValidTarballPath(path string) bool { - if utils.InvalidPath(path) || utils.IsDir(path) { + if helpers.InvalidPath(path) || helpers.IsDir(path) { return false } name := filepath.Base(path) diff --git a/src/test/e2e/bundle_test.go b/src/test/e2e/bundle_test.go index 1256443d..aa6bf7c4 100644 --- a/src/test/e2e/bundle_test.go +++ b/src/test/e2e/bundle_test.go @@ -32,12 +32,10 @@ func TestUDSCmd(t *testing.T) { } func TestUDSLogs(t *testing.T) { - bundleDir := "src/test/bundles/03-local-and-remote" - bundlePath := filepath.Join(bundleDir, fmt.Sprintf("uds-bundle-test-local-and-remote-%s-0.0.1.tar.zst", e2e.Arch)) - inspectLocal(t, bundlePath) - + inspectRemote(t, "ghcr.io/defenseunicorns/packages/uds-cli/test/publish/ghcr-test:0.0.1") stderr, _, err := e2e.UDS("logs") require.NoError(t, err) + require.Contains(t, stderr, "DEBUG") require.Contains(t, stderr, "UDSBundle") } diff --git a/src/test/e2e/commands_test.go b/src/test/e2e/commands_test.go index 3bbeba3f..72adfa44 100644 --- a/src/test/e2e/commands_test.go +++ b/src/test/e2e/commands_test.go @@ -16,7 +16,7 @@ import ( "testing" "github.com/defenseunicorns/uds-cli/src/config" - "github.com/defenseunicorns/zarf/src/pkg/utils" + "github.com/defenseunicorns/zarf/src/pkg/utils/helpers" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -173,7 +173,7 @@ func deployAndRemoveLocalAndRemoteInsecure(t *testing.T, ref string, tarballPath } func shasMatch(t *testing.T, path string, expected string) { - actual, err := utils.GetSHA256OfFile(path) + actual, err := helpers.GetSHA256OfFile(path) require.NoError(t, err) require.Equal(t, expected, actual) } diff --git a/tasks.schema.json b/tasks.schema.json index 56367f3b..7ff89d56 100644 --- a/tasks.schema.json +++ b/tasks.schema.json @@ -33,7 +33,7 @@ }, "shell": { "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfComponentActionShell", + "$ref": "#/definitions/Shell", "description": "(cmd only) Indicates a preference for a shell for the provided cmd to be executed in on supported operating systems" }, "setVariable": { @@ -106,6 +106,49 @@ "^x-": {} } }, + "Shell": { + "properties": { + "windows": { + "type": "string", + "description": "(default 'powershell') Indicates a preference for the shell to use on Windows systems (note that choosing 'cmd' will turn off migrations like touch -> New-Item)", + "examples": [ + "powershell", + "cmd", + "pwsh", + "sh", + "bash", + "gsh" + ] + }, + "linux": { + "type": "string", + "description": "(default 'sh') Indicates a preference for the shell to use on Linux systems", + "examples": [ + "sh", + "bash", + "fish", + "zsh", + "pwsh" + ] + }, + "darwin": { + "type": "string", + "description": "(default 'sh') Indicates a preference for the shell to use on macOS systems", + "examples": [ + "sh", + "bash", + "fish", + "zsh", + "pwsh" + ] + } + }, + "additionalProperties": false, + "type": "object", + "patternProperties": { + "^x-": {} + } + }, "Task": { "required": [ "name" @@ -206,18 +249,6 @@ "type": "string", "description": "The name to be used for the variable" }, - "sensitive": { - "type": "boolean", - "description": "Whether to mark this variable as sensitive to not print it in the Zarf log" - }, - "autoIndent": { - "type": "boolean", - "description": "Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_VAR_." - }, - "pattern": { - "type": "string", - "description": "An optional regex pattern that a variable value must match before a package deployment can continue." - }, "type": { "enum": [ "raw", @@ -225,49 +256,18 @@ ], "type": "string", "description": "Changes the handling of a variable to load contents differently (i.e. from a file rather than as a raw variable - templated files should be kept below 1 MiB)" - } - }, - "additionalProperties": false, - "type": "object", - "patternProperties": { - "^x-": {} - } - }, - "ZarfComponentActionShell": { - "properties": { - "windows": { - "type": "string", - "description": "(default 'powershell') Indicates a preference for the shell to use on Windows systems (note that choosing 'cmd' will turn off migrations like touch -> New-Item)", - "examples": [ - "powershell", - "cmd", - "pwsh", - "sh", - "bash", - "gsh" - ] }, - "linux": { + "pattern": { "type": "string", - "description": "(default 'sh') Indicates a preference for the shell to use on Linux systems", - "examples": [ - "sh", - "bash", - "fish", - "zsh", - "pwsh" - ] + "description": "An optional regex pattern that a variable value must match before a package deployment can continue." }, - "darwin": { - "type": "string", - "description": "(default 'sh') Indicates a preference for the shell to use on macOS systems", - "examples": [ - "sh", - "bash", - "fish", - "zsh", - "pwsh" - ] + "sensitive": { + "type": "boolean", + "description": "Whether to mark this variable as sensitive to not print it in the Zarf log" + }, + "autoIndent": { + "type": "boolean", + "description": "Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_VAR_." } }, "additionalProperties": false, diff --git a/zarf.schema.json b/zarf.schema.json index f8e53e98..f61482b7 100644 --- a/zarf.schema.json +++ b/zarf.schema.json @@ -82,6 +82,49 @@ "^x-": {} } }, + "Shell": { + "properties": { + "windows": { + "type": "string", + "description": "(default 'powershell') Indicates a preference for the shell to use on Windows systems (note that choosing 'cmd' will turn off migrations like touch -> New-Item)", + "examples": [ + "powershell", + "cmd", + "pwsh", + "sh", + "bash", + "gsh" + ] + }, + "linux": { + "type": "string", + "description": "(default 'sh') Indicates a preference for the shell to use on Linux systems", + "examples": [ + "sh", + "bash", + "fish", + "zsh", + "pwsh" + ] + }, + "darwin": { + "type": "string", + "description": "(default 'sh') Indicates a preference for the shell to use on macOS systems", + "examples": [ + "sh", + "bash", + "fish", + "zsh", + "pwsh" + ] + } + }, + "additionalProperties": false, + "type": "object", + "patternProperties": { + "^x-": {} + } + }, "ZarfBuildData": { "required": [ "terminal", @@ -118,10 +161,6 @@ "type": "array", "description": "Any migrations that have been run on this package" }, - "differential": { - "type": "boolean", - "description": "Whether this package was created with differential components" - }, "registryOverrides": { "patternProperties": { ".*": { @@ -131,6 +170,14 @@ "type": "object", "description": "Any registry domains that were overridden on package create when pulling images" }, + "differential": { + "type": "boolean", + "description": "Whether this package was created with differential components" + }, + "differentialPackageVersion": { + "type": "string", + "description": "Version of a previously built package used as the basis for creating this differential package" + }, "differentialMissing": { "items": { "type": "string" @@ -257,18 +304,13 @@ "$ref": "#/definitions/ZarfComponentImport", "description": "Import a component from another Zarf package" }, - "scripts": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/DeprecatedZarfComponentScripts", - "description": "[Deprecated] (replaced by actions) Custom commands to run before or after package deployment. This will be removed in Zarf v1.0.0." - }, - "files": { + "manifests": { "items": { "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfFile" + "$ref": "#/definitions/ZarfManifest" }, "type": "array", - "description": "Files or folders to place on disk during package deployment" + "description": "Kubernetes manifests to be included in a generated Helm chart on package deploy" }, "charts": { "items": { @@ -278,13 +320,21 @@ "type": "array", "description": "Helm charts to install during package deploy" }, - "manifests": { + "dataInjections": { "items": { "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfManifest" + "$ref": "#/definitions/ZarfDataInjection" }, "type": "array", - "description": "Kubernetes manifests to be included in a generated Helm chart on package deploy" + "description": "Datasets to inject into a container in the target cluster" + }, + "files": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/ZarfFile" + }, + "type": "array", + "description": "Files or folders to place on disk during package deployment" }, "images": { "items": { @@ -300,19 +350,16 @@ "type": "array", "description": "List of git repos to include in the package" }, - "dataInjections": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfDataInjection" - }, - "type": "array", - "description": "Datasets to inject into a container in the target cluster" - }, "extensions": { "$schema": "http://json-schema.org/draft-04/schema#", "$ref": "#/definitions/ZarfComponentExtensions", "description": "Extend component functionality with additional features" }, + "scripts": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/DeprecatedZarfComponentScripts", + "description": "[Deprecated] (replaced by actions) Custom commands to run before or after package deployment. This will be removed in Zarf v1.0.0." + }, "actions": { "$schema": "http://json-schema.org/draft-04/schema#", "$ref": "#/definitions/ZarfComponentActions", @@ -355,7 +402,7 @@ "description": "The command to run. Must specify either cmd or wait for the action to do anything." }, "shell": { - "$ref": "#/definitions/ZarfComponentActionShell", + "$ref": "#/definitions/Shell", "description": "(cmd only) Indicates a preference for a shell for the provided cmd to be executed in on supported operating systems" }, "setVariable": { @@ -414,7 +461,7 @@ }, "shell": { "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "#/definitions/ZarfComponentActionShell", + "$ref": "#/definitions/Shell", "description": "(cmd only) Indicates a preference for a shell for the provided cmd to be executed in on supported operating systems" } }, @@ -477,18 +524,6 @@ "type": "string", "description": "The name to be used for the variable" }, - "sensitive": { - "type": "boolean", - "description": "Whether to mark this variable as sensitive to not print it in the Zarf log" - }, - "autoIndent": { - "type": "boolean", - "description": "Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_VAR_." - }, - "pattern": { - "type": "string", - "description": "An optional regex pattern that a variable value must match before a package deployment can continue." - }, "type": { "enum": [ "raw", @@ -496,49 +531,18 @@ ], "type": "string", "description": "Changes the handling of a variable to load contents differently (i.e. from a file rather than as a raw variable - templated files should be kept below 1 MiB)" - } - }, - "additionalProperties": false, - "type": "object", - "patternProperties": { - "^x-": {} - } - }, - "ZarfComponentActionShell": { - "properties": { - "windows": { - "type": "string", - "description": "(default 'powershell') Indicates a preference for the shell to use on Windows systems (note that choosing 'cmd' will turn off migrations like touch -> New-Item)", - "examples": [ - "powershell", - "cmd", - "pwsh", - "sh", - "bash", - "gsh" - ] }, - "linux": { + "pattern": { "type": "string", - "description": "(default 'sh') Indicates a preference for the shell to use on Linux systems", - "examples": [ - "sh", - "bash", - "fish", - "zsh", - "pwsh" - ] + "description": "An optional regex pattern that a variable value must match before a package deployment can continue." }, - "darwin": { - "type": "string", - "description": "(default 'sh') Indicates a preference for the shell to use on macOS systems", - "examples": [ - "sh", - "bash", - "fish", - "zsh", - "pwsh" - ] + "sensitive": { + "type": "boolean", + "description": "Whether to mark this variable as sensitive to not print it in the Zarf log" + }, + "autoIndent": { + "type": "boolean", + "description": "Whether to automatically indent the variable's value (if multiline) when templating. Based on the number of chars before the start of ###ZARF_VAR_." } }, "additionalProperties": false,