Skip to content

Commit

Permalink
output format flag
Browse files Browse the repository at this point in the history
Signed-off-by: Austin Abro <[email protected]>
  • Loading branch information
AustinAbro321 committed Jan 24, 2025
1 parent 3de5338 commit 1e77aeb
Show file tree
Hide file tree
Showing 22 changed files with 602 additions and 109 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/scan-codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@ee117c905ab18f32fa0f66c2fe40ecc8013f3e04 # v3.28.4
uses: github/codeql-action/init@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql.yaml
Expand All @@ -54,6 +54,6 @@ jobs:
run: make build-cli-linux-amd

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@ee117c905ab18f32fa0f66c2fe40ecc8013f3e04 # v3.28.4
uses: github/codeql-action/analyze@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3
with:
category: "/language:${{matrix.language}}"
2 changes: 1 addition & 1 deletion .github/workflows/scorecard.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ jobs:

# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@ee117c905ab18f32fa0f66c2fe40ecc8013f3e04 # v3.28.4
uses: github/codeql-action/upload-sarif@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3
with:
sarif_file: results.sarif
2 changes: 1 addition & 1 deletion .github/workflows/test-unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ jobs:
run: make test-unit

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@0da7aa657d958d32c117fc47e1f977e7524753c7 # v5.3.0
uses: codecov/codecov-action@5a605bd92782ce0810fa3b8acc235c921b497052 # v5.2.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
2 changes: 2 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ linters-settings:
- (*github.com/spf13/cobra.Command).MarkFlagRequired
- (*github.com/spf13/pflag.FlagSet).MarkHidden
- (*github.com/spf13/pflag.FlagSet).MarkDeprecated
- fmt.Fprintln
- fmt.Fprint
sloglint:
no-mixed-args: true
key-naming-case: camel
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ require (
modernc.org/memory v1.8.0 // indirect
modernc.org/sqlite v1.34.5 // indirect
oras.land/oras-go v1.2.5 // indirect
sigs.k8s.io/controller-runtime v0.20.1
sigs.k8s.io/controller-runtime v0.20.0
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/kustomize/kustomize/v5 v5.5.0 // indirect
sigs.k8s.io/release-utils v0.8.4 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2626,8 +2626,8 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/cli-utils v0.37.2 h1:GOfKw5RV2HDQZDJlru5KkfLO1tbxqMoyn1IYUxqBpNg=
sigs.k8s.io/cli-utils v0.37.2/go.mod h1:V+IZZr4UoGj7gMJXklWBg6t5xbdThFBcpj4MrZuCYco=
sigs.k8s.io/controller-runtime v0.20.1 h1:JbGMAG/X94NeM3xvjenVUaBjy6Ui4Ogd/J5ZtjZnHaE=
sigs.k8s.io/controller-runtime v0.20.1/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU=
sigs.k8s.io/controller-runtime v0.20.0 h1:jjkMo29xEXH+02Md9qaVXfEIaMESSpy3TBWPrsfQkQs=
sigs.k8s.io/controller-runtime v0.20.0/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
sigs.k8s.io/kustomize/api v0.19.0 h1:F+2HB2mU1MSiR9Hp1NEgoU2q9ItNOaBJl0I4Dlus5SQ=
Expand Down
3 changes: 2 additions & 1 deletion site/src/content/docs/commands/zarf_package_list.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ zarf package list [flags]
### Options

```
-h, --help help for list
-h, --help help for list
-o, --output-format outputFormat Prints the output in the specified format. Valid options: table, json, yaml (default table)
```

### Options inherited from parent commands
Expand Down
3 changes: 2 additions & 1 deletion site/src/content/docs/commands/zarf_tools_get-creds.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ $ zarf tools get-creds artifact
### Options

```
-h, --help help for get-creds
-h, --help help for get-creds
-o, --output-format outputFormat Prints the output in the specified format. Valid options: table, json, yaml (default table)
```

### Options inherited from parent commands
Expand Down
4 changes: 2 additions & 2 deletions site/src/content/docs/commands/zarf_version.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ zarf version [flags]
### Options

```
-h, --help help for version
-o, --output string Output format (yaml|json)
-h, --help help for version
-o, --output-format outputFormat Output format (yaml|json)
```

### Options inherited from parent commands
Expand Down
90 changes: 70 additions & 20 deletions src/cmd/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ package cmd

import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"regexp"
Expand All @@ -16,6 +18,7 @@ import (

"github.com/AlecAivazis/survey/v2"
"github.com/defenseunicorns/pkg/helpers/v2"
goyaml "github.com/goccy/go-yaml"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"oras.land/oras-go/v2/registry"
Expand Down Expand Up @@ -406,56 +409,103 @@ func (o *packageInspectOptions) run(cmd *cobra.Command, args []string) error {
return nil
}

type packageListOptions struct{}
type packageListOptions struct {
outputFormat outputFormat
outputWriter io.Writer
cluster *cluster.Cluster
}

func newPackageListOptions() *packageListOptions {
return &packageListOptions{
outputFormat: outputTable,
// TODO accept output writer as a parameter to the root Zarf command and pass it through here
outputWriter: message.OutputWriter,
}
}

func newPackageListCommand() *cobra.Command {
o := &packageListOptions{}
o := newPackageListOptions()

cmd := &cobra.Command{
Use: "list",
Aliases: []string{"l", "ls"},
Short: lang.CmdPackageListShort,
RunE: o.run,
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
err := o.complete(ctx)
if err != nil {
return err
}
return o.run(ctx)
},
}

cmd.Flags().VarP(&o.outputFormat, "output-format", "o", "Prints the output in the specified format. Valid options: table, json, yaml")

return cmd
}

func (o *packageListOptions) run(cmd *cobra.Command, _ []string) error {
timeoutCtx, cancel := context.WithTimeout(cmd.Context(), cluster.DefaultTimeout)
func (o *packageListOptions) complete(ctx context.Context) error {
timeoutCtx, cancel := context.WithTimeout(ctx, cluster.DefaultTimeout)
defer cancel()
c, err := cluster.NewClusterWithWait(timeoutCtx)
if err != nil {
return err
}
o.cluster = c
return nil
}

ctx := cmd.Context()
deployedZarfPackages, err := c.GetDeployedZarfPackages(ctx)
// packageListInfo represents the package information for output.
type packageListInfo struct {
Package string `json:"package"`
Version string `json:"version"`
Components []string `json:"components"`
}

func (o *packageListOptions) run(ctx context.Context) error {
deployedZarfPackages, err := o.cluster.GetDeployedZarfPackages(ctx)
if err != nil && len(deployedZarfPackages) == 0 {
return fmt.Errorf("unable to get the packages deployed to the cluster: %w", err)
}

// Populate a matrix of all the deployed packages
packageData := [][]string{}

var packageList []packageListInfo
for _, pkg := range deployedZarfPackages {
var components []string

for _, component := range pkg.DeployedComponents {
components = append(components, component.Name)
}

packageData = append(packageData, []string{
pkg.Name, pkg.Data.Metadata.Version, fmt.Sprintf("%v", components),
packageList = append(packageList, packageListInfo{
Package: pkg.Name,
Version: pkg.Data.Metadata.Version,
Components: components,
})
}

header := []string{"Package", "Version", "Components"}
message.TableWithWriter(message.OutputWriter, header, packageData)

// Print out any unmarshalling errors
if err != nil {
return fmt.Errorf("unable to read all of the packages deployed to the cluster: %w", err)
switch o.outputFormat {
case outputJSON:
output, err := json.MarshalIndent(packageList, "", " ")
if err != nil {
return err
}
fmt.Fprintln(o.outputWriter, string(output))
case outputYAML:
output, err := goyaml.Marshal(packageList)
if err != nil {
return err
}
fmt.Fprint(o.outputWriter, string(output))
case outputTable:
header := []string{"Package", "Version", "Components"}
var packageData [][]string
for _, info := range packageList {
packageData = append(packageData, []string{
info.Package, info.Version, fmt.Sprintf("%v", info.Components),
})
}
message.TableWithWriter(o.outputWriter, header, packageData)
default:
return fmt.Errorf("unsupported output format: %s", o.outputFormat)
}
return nil
}
Expand Down
124 changes: 124 additions & 0 deletions src/cmd/package_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors

// Package cmd contains the CLI commands for Zarf.
package cmd

import (
"bytes"
"context"
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"

"github.com/stretchr/testify/require"
"github.com/zarf-dev/zarf/src/api/v1alpha1"
"github.com/zarf-dev/zarf/src/config"
"github.com/zarf-dev/zarf/src/pkg/cluster"
"github.com/zarf-dev/zarf/src/types"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)

func TestPackageList(t *testing.T) {
t.Parallel()
tests := []struct {
name string
outputFormat outputFormat
file string
}{
{
name: "json package list",
outputFormat: outputJSON,
file: "expected.json",
},
{
name: "yaml package list",
outputFormat: outputYAML,
file: "expected.yaml",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
ctx := context.Background()
c := &cluster.Cluster{
Clientset: fake.NewClientset(),
}

packages := []types.DeployedPackage{
{
Name: "package1",
Data: v1alpha1.ZarfPackage{
Metadata: v1alpha1.ZarfMetadata{
Version: "0.42.0",
},
},
DeployedComponents: []types.DeployedComponent{
{
Name: "component1",
},
{
Name: "component2",
},
},
},
{
Name: "package2",
Data: v1alpha1.ZarfPackage{
Metadata: v1alpha1.ZarfMetadata{
Version: "1.0.0",
},
},
DeployedComponents: []types.DeployedComponent{
{
Name: "component3",
},
{
Name: "component4",
},
},
},
}

for _, p := range packages {
b, err := json.Marshal(p)
require.NoError(t, err)
secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: strings.Join([]string{config.ZarfPackagePrefix, p.Name}, ""),
Namespace: "zarf",
Labels: map[string]string{
cluster.ZarfPackageInfoLabel: p.Name,
},
},
Data: map[string][]byte{
"data": b,
},
}
_, err = c.Clientset.CoreV1().Secrets("zarf").Create(ctx, &secret, metav1.CreateOptions{})
require.NoError(t, err)
}
buf := new(bytes.Buffer)
listOpts := packageListOptions{
outputFormat: tt.outputFormat,
outputWriter: buf,
cluster: c,
}
err := listOpts.run(ctx)
require.NoError(t, err)
b, err := os.ReadFile(filepath.Join("testdata", "package-list", tt.file))
require.NoError(t, err)
if tt.outputFormat == outputJSON {
require.JSONEq(t, string(b), buf.String())
}
if tt.outputFormat == outputYAML {
require.YAMLEq(t, string(b), buf.String())
}
})
}
}
Loading

0 comments on commit 1e77aeb

Please sign in to comment.