Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dev): observation print commands #762

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/cli-commands/lula_dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ Collection of dev commands to make dev life easier
* [lula](./lula.md) - Risk Management as Code
* [lula dev get-resources](./lula_dev_get-resources.md) - Get Resources from a Lula Validation Manifest
* [lula dev lint](./lula_dev_lint.md) - Lint validation files against schema
* [lula dev print](./lula_dev_print.md) - Print Resources or Lula Validation from an Assessment Observation
* [lula dev validate](./lula_dev_validate.md) - Run an individual Lula validation.

58 changes: 58 additions & 0 deletions docs/cli-commands/lula_dev_print.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
title: lula dev print
description: Lula CLI command reference for <code>lula dev print</code>.
type: docs
---
## lula dev print

Print Resources or Lula Validation from an Assessment Observation

### Synopsis


Print out data about an Observation.
Given "--resources", the command will print the JSON resources input that were provided to a Lula Validation, as identified by a given observation and assessment results file.
Given "--validation", the command will print the Lula Validation that generated a given observation, as identified by a given observation, assessment results file, and component definition file.


```
lula dev print [flags]
```

### Examples

```

To print resources from lula validation manifest:
lula dev print --resources --assessment /path/to/assessment.yaml --observation-uuid <observation-uuid>

To print resources from lula validation manifest to output file:
lula dev print --resources --assessment /path/to/assessment.yaml --observation-uuid <observation-uuid> --output-file /path/to/output.json

To print the lula validation that generated a given observation:
lula dev print --validation --component /path/to/component.yaml --assessment /path/to/assessment.yaml --observation-uuid <observation-uuid>

```

### Options

```
-a, --assessment string the path to an assessment-results file
-c, --component string the path to a validation manifest file
-h, --help help for print
-u, --observation-uuid string the observation uuid
-o, --output-file string the path to write the resources json
-r, --resources true if the user is printing resources
-v, --validation true if the user is printing validation
```

### Options inherited from parent commands

```
-l, --log-level string Log level when running Lula. Valid options are: warn, info, debug, trace (default "info")
```

### SEE ALSO

* [lula dev](./lula_dev.md) - Collection of dev commands to make dev life easier

41 changes: 39 additions & 2 deletions src/cmd/dev/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ import (
"context"
"fmt"
"io"
"os"
"strings"
"time"

oscalTypes_1_1_2 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-2"
"github.com/spf13/cobra"
"sigs.k8s.io/yaml"

"github.com/defenseunicorns/lula/src/config"
"github.com/defenseunicorns/lula/src/pkg/common"
"github.com/defenseunicorns/lula/src/pkg/message"
"github.com/defenseunicorns/lula/src/types"
"github.com/spf13/cobra"
"sigs.k8s.io/yaml"
)

const STDIN = "0"
Expand Down Expand Up @@ -104,3 +107,37 @@ func RunSingleValidation(ctx context.Context, validationBytes []byte, opts ...ty

return lulaValidation, nil
}

// GetObservationByUuid returns the observation with the given UUID
func GetObservationByUuid(assessmentResults *oscalTypes_1_1_2.AssessmentResults, observationUuid string) (*oscalTypes_1_1_2.Observation, error) {
if assessmentResults == nil {
return nil, fmt.Errorf("assessment results is nil")
}

for _, result := range assessmentResults.Results {
if result.Observations != nil {
for _, observation := range *result.Observations {
if observation.UUID == observationUuid {
return &observation, nil
}
}
}
}
return nil, fmt.Errorf("observation with uuid %s not found", observationUuid)
}

// writeResources writes the resources to a file or stdout
func writeResources(data types.DomainResources, filepath string) error {
jsonData := message.JSONValue(data)

// If a filepath is provided, write the JSON data to the file.
if filepath != "" {
err := os.WriteFile(filepath, []byte(jsonData), 0600)
if err != nil {
return fmt.Errorf("error writing resource JSON to file: %v", err)
}
} else {
message.Printf("%s", jsonData)
}
return nil
}
32 changes: 32 additions & 0 deletions src/cmd/dev/common_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package dev_test

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/defenseunicorns/lula/src/cmd/dev"
"github.com/defenseunicorns/lula/src/internal/testhelpers"
)

func TestGetObservationByUuid(t *testing.T) {
t.Parallel()

oscalModel := testhelpers.OscalFromPath(t, "../../test/unit/common/oscal/valid-assessment-results-with-resources.yaml")
assessment := oscalModel.AssessmentResults
require.NotNil(t, assessment)

t.Run("Test get observation by uuid - found", func(t *testing.T) {
observation, err := dev.GetObservationByUuid(assessment, "92cb3cad-bbcd-431a-aaa9-cd47275a3982")
require.NoError(t, err)
require.NotNil(t, observation)
})

t.Run("Test get observation by uuid - not found", func(t *testing.T) {
observation, err := dev.GetObservationByUuid(assessment, "invalid-uuid")
assert.Nil(t, observation)
require.ErrorContains(t, err, "observation with uuid invalid-uuid not found")
})

}
21 changes: 4 additions & 17 deletions src/cmd/dev/get-resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package dev
import (
"context"
"fmt"
"os"

"github.com/defenseunicorns/lula/src/cmd/common"
"github.com/defenseunicorns/lula/src/pkg/message"
Expand Down Expand Up @@ -53,7 +52,10 @@ var getResourcesCmd = &cobra.Command{
message.Fatalf(err, "error running dev get-resources: %v", err)
}

writeResources(collection, getResourcesOpts.OutputFile)
err = writeResources(collection, getResourcesOpts.OutputFile)
if err != nil {
message.Fatalf(err, "error writing resources: %v", err)
}

spinner.Success()
},
Expand Down Expand Up @@ -85,18 +87,3 @@ func DevGetResources(ctx context.Context, validationBytes []byte, spinner *messa

return *lulaValidation.DomainResources, nil
}

func writeResources(data types.DomainResources, filepath string) {
jsonData := message.JSONValue(data)

// If a filepath is provided, write the JSON data to the file.
if filepath != "" {
err := os.WriteFile(filepath, []byte(jsonData), 0600) // G306
if err != nil {
message.Fatalf(err, "error writing resource JSON to file: %v", err)
}
} else {
// Else print to stdout
fmt.Println(jsonData)
}
}
Loading