Repository: sonatype-nexus-community/nancy
Pull request #213 (2021-01-20 21:17:32)

use new AbsoluteReportHTMLURL
As of IQ 104, the report urls returned in the old field are relative urls. This PR uses a new field populated with an absolute url for viewing the report.

TODO: Update to use a released version of `go-sona-types` when possible.

cc @bhamail / @DarthHater



Patch:
diff --git a/go.mod b/go.mod
index 7e90dbd..6f0e413 100644
--- a/go.mod
+++ b/go.mod
@@ -24,7 +24,7 @@ require (
 	github.com/sdboyer/constext v0.0.0-20170321163424-836a14457353 // indirect
 	github.com/shopspring/decimal v1.2.0
 	github.com/sirupsen/logrus v1.6.0
-	github.com/sonatype-nexus-community/go-sona-types v0.0.8
+	github.com/sonatype-nexus-community/go-sona-types v0.0.10
 	github.com/spf13/afero v1.3.4 // indirect
 	github.com/spf13/cast v1.3.1 // indirect
 	github.com/spf13/cobra v1.0.0
diff --git a/go.sum b/go.sum
index 38e05cf..772db06 100644
--- a/go.sum
+++ b/go.sum
@@ -257,8 +257,8 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1
 github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
 github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
-github.com/sonatype-nexus-community/go-sona-types v0.0.8 h1:6xb9BIC2w3y4kF/xQA25Zs6Yrl8ZqFkfH77AKPaG4RA=
-github.com/sonatype-nexus-community/go-sona-types v0.0.8/go.mod h1:uou8FGf9R5Nz1c6BfSM3v9K7g0R6faTYoxLh9Ybeht8=
+github.com/sonatype-nexus-community/go-sona-types v0.0.10 h1:VW+OE1vAjBwwRCz7jz4xcBbUn1j3bz1gFnEw1YYmYGs=
+github.com/sonatype-nexus-community/go-sona-types v0.0.10/go.mod h1:uou8FGf9R5Nz1c6BfSM3v9K7g0R6faTYoxLh9Ybeht8=
 github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
 github.com/spf13/afero v1.3.4 h1:8q6vk3hthlpb2SouZcnBVKboxWQWMDNF38bwholZrJc=
diff --git a/internal/cmd/iq.go b/internal/cmd/iq.go
index 03389e4..4384340 100644
--- a/internal/cmd/iq.go
+++ b/internal/cmd/iq.go
@@ -20,6 +20,7 @@ import (
 	"errors"
 	"fmt"
 	"github.com/spf13/pflag"
+	"io"
 	"os"
 	"path"
 
@@ -249,17 +250,24 @@ func auditWithIQServer(purls []string) error {
 	}
 
 	logLady.WithField("res", res).Debug("Successful in communicating with IQ Server")
+	showPolicyActionMessage(res, os.Stdout)
 	switch res.PolicyAction {
-	case "Failure":
-		fmt.Println("Hi, Nancy here, you have some policy violations to clean up!")
-		fmt.Println("Report URL: ", res.ReportHTMLURL)
+	case iq.PolicyActionFailure:
 		return customerrors.ErrorExit{ExitCode: 1}
-	case "Warning":
-		fmt.Println("Read, read, read. That's all I can say. There are policy warnings to investigate!")
-		fmt.Println("Report URL: ", res.ReportHTMLURL)
-	default:
-		fmt.Println("Wonderbar! No policy violations reported for this audit!")
-		fmt.Println("Report URL: ", res.ReportHTMLURL)
 	}
 	return nil
 }
+
+func showPolicyActionMessage(res iq.StatusURLResult, writer io.Writer) {
+	switch res.PolicyAction {
+	case iq.PolicyActionFailure:
+		_, _ = fmt.Fprintln(writer, "Hi, Nancy here, you have some policy violations to clean up!")
+		_, _ = fmt.Fprintln(writer, "Report URL: ", res.AbsoluteReportHTMLURL)
+	case iq.PolicyActionWarning:
+		_, _ = fmt.Fprintln(writer, "Read, read, read. That's all I can say. There are policy warnings to investigate!")
+		_, _ = fmt.Fprintln(writer, "Report URL: ", res.AbsoluteReportHTMLURL)
+	default:
+		_, _ = fmt.Fprintln(writer, "Wonderbar! No policy violations reported for this audit!")
+		_, _ = fmt.Fprintln(writer, "Report URL: ", res.AbsoluteReportHTMLURL)
+	}
+}


Test patch:
diff --git a/internal/cmd/iq_test.go b/internal/cmd/iq_test.go
index 79768c8..999cc0f 100644
--- a/internal/cmd/iq_test.go
+++ b/internal/cmd/iq_test.go
@@ -17,6 +17,8 @@
 package cmd
 
 import (
+	"bufio"
+	"bytes"
 	"errors"
 	"fmt"
 	"io/ioutil"
@@ -185,6 +187,11 @@ func (s mockIqServer) AuditPackages(purls []string) (iq.StatusURLResult, error)
 	return s.auditPackagesStatusURLResult, s.auditPackagesErr
 }
 
+//noinspection GoUnusedParameter
+func (s mockIqServer) AuditWithSbom(sbom string) (iq.StatusURLResult, error) {
+	return iq.StatusURLResult{}, fmt.Errorf("mock AuditWithSbom not implemented")
+}
+
 // use compiler to ensure interface is implemented by mock
 var _ iq.IServer = (*mockIqServer)(nil)
 
@@ -393,3 +400,18 @@ func TestIqCreatorOptionsLogging(t *testing.T) {
 	logLady.Level = logrus.DebugLevel
 	assert.NotNil(t, iqCreator.create())
 }
+
+func Test_showPolicyActionMessage(t *testing.T) {
+	verifyReportURL(t, "anythingElse") //default policy action
+	verifyReportURL(t, iq.PolicyActionWarning)
+	verifyReportURL(t, iq.PolicyActionFailure)
+}
+
+func verifyReportURL(t *testing.T, policyAction string) {
+	var buf bytes.Buffer
+	bufWriter := bufio.NewWriter(&buf)
+	theURL := "someURL"
+	showPolicyActionMessage(iq.StatusURLResult{AbsoluteReportHTMLURL: theURL, PolicyAction: policyAction}, bufWriter)
+	bufWriter.Flush()
+	assert.True(t, strings.Contains(buf.String(), "Report URL:  "+theURL), buf.String())
+}