Skip to content
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v29.4.0+incompatible h1:+IjXULMetlvWJiuSI0Nbor36lcJ5BTcVpUmB21KBoVM=
github.com/docker/cli v29.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker-credential-helpers v0.9.4 h1:76ItO69/AP/V4yT9V4uuuItG0B1N8hvt0T0c0NN/DzI=
github.com/docker/docker-credential-helpers v0.9.4/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c=
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
Expand Down
44 changes: 2 additions & 42 deletions internal/util/render/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -1064,9 +1064,9 @@ func captureStepResult(fn kptfilev1.Function, fnResults *fnresult.ResultList, re
last := fnResults.Items[len(fnResults.Items)-1]
step.Stderr = last.Stderr
step.ExitCode = last.ExitCode
step.Results = frameworkResultsToItems(last.Results)
step.Results = last.Results
for _, ri := range step.Results {
if ri.Severity == string(framework.Error) {
if ri.Severity == framework.Error {
step.ErrorResults = append(step.ErrorResults, ri)
}
}
Expand All @@ -1090,43 +1090,3 @@ func preExecFailureStep(fn kptfilev1.Function, err error) kptfilev1.PipelineStep
ExecutionError: err.Error(),
}
}

// frameworkResultsToItems converts framework.Results to []ResultItem.
func frameworkResultsToItems(results framework.Results) []kptfilev1.ResultItem {
if len(results) == 0 {
return nil
}
items := make([]kptfilev1.ResultItem, len(results))
for i, r := range results {
items[i] = kptfilev1.ResultItem{
Message: r.Message,
Severity: string(r.Severity),
}
if r.ResourceRef != nil {
items[i].ResourceRef = &kptfilev1.ResourceRef{
APIVersion: r.ResourceRef.APIVersion,
Kind: r.ResourceRef.Kind,
Name: r.ResourceRef.Name,
Namespace: r.ResourceRef.Namespace,
}
}
if r.Field != nil {
items[i].Field = &kptfilev1.FieldRef{
Path: r.Field.Path,
}
if r.Field.CurrentValue != nil {
items[i].Field.CurrentValue = fmt.Sprintf("%v", r.Field.CurrentValue)
}
if r.Field.ProposedValue != nil {
items[i].Field.ProposedValue = fmt.Sprintf("%v", r.Field.ProposedValue)
}
}
if r.File != nil {
items[i].File = &kptfilev1.FileRef{
Path: r.File.Path,
Index: r.File.Index,
}
}
}
return items
}
55 changes: 7 additions & 48 deletions internal/util/render/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (

"github.com/kptdev/kpt/internal/pkg"
"github.com/kptdev/kpt/internal/types"
fnresult "github.com/kptdev/kpt/pkg/api/fnresult/v1"
fnresultv1 "github.com/kptdev/kpt/pkg/api/fnresult/v1"
kptfilev1 "github.com/kptdev/kpt/pkg/api/kptfile/v1"
fnruntime "github.com/kptdev/kpt/pkg/fn/runtime"
"github.com/kptdev/kpt/pkg/kptfile/kptfileutil"
Expand Down Expand Up @@ -790,12 +790,12 @@ func TestBuildRenderStatus_UsesExecPathForErrorSummary(t *testing.T) {
}

func TestCaptureStepResult_FromFnResults(t *testing.T) {
fnResults := fnresult.NewResultList()
fnResults.Items = append(fnResults.Items, fnresult.Result{
fnResults := fnresultv1.NewResultList()
fnResults.Items = append(fnResults.Items, fnresultv1.Result{
Image: "gatekeeper:latest",
ExitCode: 1,
Stderr: "validation failed",
Results: framework.Results{
Results: []fnresultv1.ResultItem{
{Message: "banned key found", Severity: framework.Error,
ResourceRef: &yaml.ResourceIdentifier{
TypeMeta: yaml.TypeMeta{APIVersion: "v1", Kind: "ConfigMap"},
Expand All @@ -818,7 +818,7 @@ func TestCaptureStepResult_FromFnResults(t *testing.T) {

// First result — error with full resource ref and file
assert.Equal(t, "banned key found", step.Results[0].Message)
assert.Equal(t, "error", step.Results[0].Severity)
assert.Equal(t, framework.Error, step.Results[0].Severity)
assert.Equal(t, "v1", step.Results[0].ResourceRef.APIVersion)
assert.Equal(t, "ConfigMap", step.Results[0].ResourceRef.Kind)
assert.Equal(t, "my-cm", step.Results[0].ResourceRef.Name)
Expand All @@ -828,7 +828,7 @@ func TestCaptureStepResult_FromFnResults(t *testing.T) {

// Second result — warning, no resource ref
assert.Equal(t, "missing label", step.Results[1].Message)
assert.Equal(t, "warning", step.Results[1].Severity)
assert.Equal(t, framework.Warning, step.Results[1].Severity)
assert.Nil(t, step.Results[1].ResourceRef)

// ErrorResults should only contain the error-severity item
Expand All @@ -837,7 +837,7 @@ func TestCaptureStepResult_FromFnResults(t *testing.T) {
}

func TestCaptureStepResult_NoNewItems(t *testing.T) {
fnResults := fnresult.NewResultList()
fnResults := fnresultv1.NewResultList()
fn := kptfilev1.Function{Image: "set-namespace:v1"}
step := captureStepResult(fn, fnResults, 0, fmt.Errorf("output resource list must contain only KRM resources"))

Expand Down Expand Up @@ -867,47 +867,6 @@ func TestPreExecFailureStep_EmptyFn(t *testing.T) {
assert.Equal(t, "no functions", step.ExecutionError)
}

func TestFrameworkResultsToItems_Nil(t *testing.T) {
items := frameworkResultsToItems(nil)
assert.Nil(t, items)
}

func TestFrameworkResultsToItems_WithFieldRef(t *testing.T) {
results := framework.Results{
{
Message: "wrong value",
Severity: framework.Error,
Field: &framework.Field{
Path: ".spec.replicas",
CurrentValue: "invalid",
ProposedValue: 3,
},
},
}
items := frameworkResultsToItems(results)
assert.Len(t, items, 1)
assert.Equal(t, ".spec.replicas", items[0].Field.Path)
assert.Equal(t, "invalid", items[0].Field.CurrentValue)
assert.Equal(t, "3", items[0].Field.ProposedValue)
}

func TestFrameworkResultsToItems_NilFieldValues(t *testing.T) {
results := framework.Results{
{
Message: "field info",
Severity: framework.Info,
Field: &framework.Field{
Path: ".spec.replicas",
},
},
}
items := frameworkResultsToItems(results)
assert.Len(t, items, 1)
assert.Equal(t, ".spec.replicas", items[0].Field.Path)
assert.Empty(t, items[0].Field.CurrentValue)
assert.Empty(t, items[0].Field.ProposedValue)
}

func TestUpdateRenderStatus_WritesRenderStatus(t *testing.T) {
mockFS := filesys.MakeFsInMemory()
rootPath := rootString
Expand Down
72 changes: 71 additions & 1 deletion pkg/api/fnresult/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// +kubebuilder:object:generate=true
package v1

import (
"fmt"
"strings"

"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/kustomize/kyaml/fn/framework"
"sigs.k8s.io/kustomize/kyaml/yaml"
)

//go:generate go run sigs.k8s.io/controller-tools/cmd/controller-gen@v0.21.0 object:headerFile="../../../../hack/boilerplate.go.txt",year=$YEAR_GEN

// Result contains the structured result from an individual function
type Result struct {
// Image is the full name of the image that generates this result
Expand All @@ -38,7 +44,7 @@ type Result struct {
// ExitCode is the exit code from running the function
ExitCode int `yaml:"exitCode"`
// Results is the list of results for the function
Results framework.Results `yaml:"results,omitempty"`
Results []ResultItem `yaml:"results,omitempty"`
}

const (
Expand Down Expand Up @@ -88,3 +94,67 @@ func NewResultList() *ResultList {
Items: []Result{},
}
}

// ResultItem is a modified version of sigs.k8s.io/kustomize/kyaml/fn/framework.Result
// with a simplified Field field.
type ResultItem struct {
Message string `yaml:"message,omitempty" json:"message,omitempty"`

Severity framework.Severity `yaml:"severity,omitempty" json:"severity,omitempty"`

ResourceRef *yaml.ResourceIdentifier `yaml:"resourceRef,omitempty" json:"resourceRef,omitempty"`

Field *Field `yaml:"field,omitempty" json:"field,omitempty"`

File *framework.File `yaml:"file,omitempty" json:"file,omitempty"`

Tags map[string]string `yaml:"tags,omitempty" json:"tags,omitempty"`
}

// String provides a human-readable message for the result item
func (i *ResultItem) String() string {
identifier := i.ResourceRef
var idStringList []string
if identifier != nil {
if identifier.APIVersion != "" {
idStringList = append(idStringList, identifier.APIVersion)
}
if identifier.Kind != "" {
idStringList = append(idStringList, identifier.Kind)
}
if identifier.Namespace != "" {
idStringList = append(idStringList, identifier.Namespace)
}
if identifier.Name != "" {
idStringList = append(idStringList, identifier.Name)
}
}
formatString := "[%s]"
severity := i.Severity
// We default Severity to Info when converting a result to a message.
if i.Severity == "" {
severity = framework.Info
}
list := []interface{}{severity}
if len(idStringList) > 0 {
formatString += " %s"
list = append(list, strings.Join(idStringList, "/"))
}
if i.Field != nil {
formatString += " %s"
list = append(list, i.Field.Path)
}
formatString += ": %s"
list = append(list, i.Message)
return fmt.Sprintf(formatString, list...)
}

// Field is a modified version of sigs.k8s.io/kustomize/kyaml/fn/framework.Field
// where CurrentValue and ProposedValue is a string instead of an interface{}.
Comment thread
mozesl-nokia marked this conversation as resolved.
Outdated
type Field struct {
Path string `yaml:"path,omitempty" json:"path,omitempty"`

CurrentValue string `yaml:"currentValue,omitempty" json:"currentValue,omitempty"`

ProposedValue string `yaml:"proposedValue,omitempty" json:"proposedValue,omitempty"`
}
121 changes: 121 additions & 0 deletions pkg/api/fnresult/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading