Merge pull request #927 from cloudskiff/fix/jsonHTML

Fix JSON diff formatting in HTML output
main
Raphaël 2021-08-23 16:32:34 +02:00 committed by GitHub
commit d2339ab2c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 18 deletions

View File

@ -98,7 +98,7 @@ func (c *Console) Write(analysis *analyser.Analysis) error {
if change.Type == diff.UPDATE { if change.Type == diff.UPDATE {
if change.JsonString { if change.JsonString {
prefix := " " prefix := " "
fmt.Printf("%s%s\n%s%s\n", whiteSpace, pref, prefix, jsonDiff(change.From, change.To, prefix)) fmt.Printf("%s%s\n%s%s\n", whiteSpace, pref, prefix, jsonDiff(change.From, change.To, isatty.IsTerminal(os.Stdout.Fd())))
continue continue
} }
} }
@ -207,22 +207,22 @@ func groupByType(resources []*resource.Resource) (map[string][]*resource.Resourc
return result, keys return result, keys
} }
func jsonDiff(a, b interface{}, prefix string) string { func jsonDiff(a, b interface{}, coloring bool) string {
aStr := fmt.Sprintf("%s", a) aStr := fmt.Sprintf("%s", a)
bStr := fmt.Sprintf("%s", b) bStr := fmt.Sprintf("%s", b)
d := gojsondiff.New() d := gojsondiff.New()
var aJson map[string]interface{} var aJson map[string]interface{}
_ = json.Unmarshal([]byte(aStr), &aJson) _ = json.Unmarshal([]byte(aStr), &aJson)
diff, _ := d.Compare([]byte(aStr), []byte(bStr)) result, _ := d.Compare([]byte(aStr), []byte(bStr))
f := formatter.NewAsciiFormatter(aJson, formatter.AsciiFormatterConfig{ f := formatter.NewAsciiFormatter(aJson, formatter.AsciiFormatterConfig{
Coloring: isatty.IsTerminal(os.Stdout.Fd()), Coloring: coloring,
}) })
// Set foreground green color for added lines and red color for deleted lines // Set foreground green color for added lines and red color for deleted lines
formatter.AsciiStyles = map[string]string{ formatter.AsciiStyles = map[string]string{
"+": "32", "+": "32",
"-": "31", "-": "31",
} }
diffStr, _ := f.Format(diff) diffStr, _ := f.Format(result)
return diffStr return diffStr
} }

View File

@ -9,6 +9,7 @@ import (
"math" "math"
"os" "os"
"reflect" "reflect"
"regexp"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -123,7 +124,7 @@ func (c *HTML) Write(analysis *analyser.Analysis) error {
case diff.UPDATE: case diff.UPDATE:
prefix := fmt.Sprintf("%s %s:", "~", path) prefix := fmt.Sprintf("%s %s:", "~", path)
if change.JsonString { if change.JsonString {
_, _ = fmt.Fprintf(&buf, "%s%s<br>%s%s<br>", whiteSpace, prefix, whiteSpace, jsonDiff(change.From, change.To, whiteSpace)) _, _ = fmt.Fprintf(&buf, "%s%s<br>%s%s<br>", whiteSpace, prefix, whiteSpace, jsonDiffHTML(change.From, change.To))
continue continue
} }
_, _ = fmt.Fprintf(&buf, "%s%s <span class=\"code-box-line-delete\">%s</span> => <span class=\"code-box-line-create\">%s</span>", whiteSpace, prefix, htmlPrettify(change.From), htmlPrettify(change.To)) _, _ = fmt.Fprintf(&buf, "%s%s <span class=\"code-box-line-delete\">%s</span> => <span class=\"code-box-line-create\">%s</span>", whiteSpace, prefix, htmlPrettify(change.From), htmlPrettify(change.To))
@ -194,3 +195,15 @@ func htmlPrettify(resource interface{}) string {
} }
return awsutil.Prettify(resource) return awsutil.Prettify(resource)
} }
func jsonDiffHTML(a, b interface{}) string {
diffStr := jsonDiff(a, b, false)
re := regexp.MustCompile(`(?m)^(?P<value>(\-)(.*))$`)
diffStr = re.ReplaceAllString(diffStr, `<span class="code-box-line-delete">$value</span>`)
re = regexp.MustCompile(`(?m)^(?P<value>(\+)(.*))$`)
diffStr = re.ReplaceAllString(diffStr, `<span class="code-box-line-create">$value</span>`)
return diffStr
}

View File

@ -127,11 +127,12 @@ func TestHTML_Write(t *testing.T) {
}, },
}, },
{ {
JsonString: true,
Change: diff.Change{ Change: diff.Change{
Type: diff.UPDATE, Type: diff.UPDATE,
Path: []string{"Policies", "0"}, Path: []string{"policy"},
From: resource.Resource{}, From: `{"Statement":[{"Action":["s3:GetObjectVersion"],"Effect":"Allow","Principal":"*","Resource":"arn:aws:s3:::tmxxrn.foobar.driftctl-test.com/*","Sid":"PublicRead"}],"Version":"2012-10-17"}`,
To: resource.Resource{Id: "093cd6ba-cf6d-4800-b252-6a50ca8903cd", Type: "aws_iam_policy"}, To: `{"Statement":[{"Action":["*"],"Effect":"Deny","Principal":"*","Resource":"arn:aws:s3:::tmxxrn.foobar.driftctl-test.com/b/*","Sid":"PublicReadWrite"},{"Effect":"Deny","Sid":"PublicReadWrite"}],"Version":"2021-10-17","Test":[]}`,
}, },
}, },
{ {

View File

@ -518,15 +518,37 @@ input[type="search"], select {
<span role="cell" data-type="resource-type">aws_diff_resource</span> <span role="cell" data-type="resource-type">aws_diff_resource</span>
</div> </div>
<pre class="code-box"> <pre class="code-box">
<code class="code-box-line">&emsp;- path.to.fields.[0]: <span class="code-box-line-delete">"value"</span><br>&emsp;~ path.to.fields.[1]: <span class="code-box-line-delete">12</span> => <span class="code-box-line-create">"12"</span><br>&emsp;- group_ids: <span class="code-box-line-delete">["a071314398026"]</span><br>&emsp;~ Policies.[0]: <span class="code-box-line-delete">{ <code class="code-box-line">&emsp;- path.to.fields.[0]: <span class="code-box-line-delete">"value"</span><br>&emsp;~ path.to.fields.[1]: <span class="code-box-line-delete">12</span> => <span class="code-box-line-create">"12"</span><br>&emsp;- group_ids: <span class="code-box-line-delete">["a071314398026"]</span><br>&emsp;~ policy:<br>&emsp; {
Id: "", "Statement": [
Type: "", {
Source: <nil> "Action": [
}</span> => <span class="code-box-line-create">{ <span class="code-box-line-delete">- "s3:GetObjectVersion"</span>
Id: "093cd6ba-cf6d-4800-b252-6a50ca8903cd", <span class="code-box-line-create">+ "*"</span>
Type: "aws_iam_policy", ],
Source: <nil> <span class="code-box-line-delete">- "Effect": "Allow",</span>
}</span><br>&emsp;+ Tags.[0].Name: <span class="code-box-line-create">"test"</span><br>&emsp;~ InstanceInitiatedShutdownBehavior: <span class="code-box-line-delete">""</span> => <span class="code-box-line-create">null</span><br></code> <span class="code-box-line-create">+ "Effect": "Deny",</span>
"Principal": "*",
<span class="code-box-line-delete">- "Resource": "arn:aws:s3:::tmxxrn.foobar.driftctl-test.com/*",</span>
<span class="code-box-line-create">+ "Resource": "arn:aws:s3:::tmxxrn.foobar.driftctl-test.com/b/*",</span>
<span class="code-box-line-delete">- "Sid": "PublicRead"</span>
<span class="code-box-line-create">+ "Sid": "PublicReadWrite"</span>
}
<span class="code-box-line-create">+ {</span>
<span class="code-box-line-create">+ "Action": [</span>
<span class="code-box-line-create">+ "*"</span>
<span class="code-box-line-create">+ ],</span>
<span class="code-box-line-create">+ "Effect": "Deny",</span>
<span class="code-box-line-create">+ "Principal": "*",</span>
<span class="code-box-line-create">+ "Resource": "arn:aws:s3:::tmxxrn.foobar.driftctl-test.com/b/*",</span>
<span class="code-box-line-create">+ "Sid": "PublicReadWrite"</span>
<span class="code-box-line-create">+ }</span>
],
<span class="code-box-line-delete">- "Version": "2012-10-17"</span>
<span class="code-box-line-create">+ "Version": "2021-10-17"</span>
<span class="code-box-line-create">+ "Test": [</span>
<span class="code-box-line-create">+ ]</span>
}
<br>&emsp;+ Tags.[0].Name: <span class="code-box-line-create">"test"</span><br>&emsp;~ InstanceInitiatedShutdownBehavior: <span class="code-box-line-delete">""</span> => <span class="code-box-line-create">null</span><br></code>
</pre> </pre>
</div> </div>