Skip to content

Commit

Permalink
Add a compare API and view (#21)
Browse files Browse the repository at this point in the history
* Make compare API richer

* Add compare view

* Unified diff

* Version chooser

* Use a directive for syntax highlighting

* Diff UI

* Do not include empty diffs in resource_diff
  • Loading branch information
raphink authored and cryptobioz committed Aug 2, 2017
1 parent f8ca6ee commit 7192158
Show file tree
Hide file tree
Showing 11 changed files with 393 additions and 19 deletions.
51 changes: 36 additions & 15 deletions compare/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package compare

import (
"fmt"
"sort"
"strings"

log "github.com/Sirupsen/logrus"
Expand All @@ -19,14 +20,6 @@ func stateResources(state types.State) (res []string) {
return
}

// Return all attributes of a resource
func resourceAttributes(res types.Resource) (attrs []string) {
for _, a := range res.Attributes {
attrs = append(attrs, a.Key)
}
return
}

// Returns elements only in s1
func sliceDiff(s1, s2 []string) (diff []string) {
for _, e1 := range s1 {
Expand Down Expand Up @@ -73,6 +66,15 @@ func getResource(state types.State, key string) (res types.Resource) {
return
}

// Return all attributes of a resource
func resourceAttributes(res types.Resource) (attrs []string) {
for _, a := range res.Attributes {
attrs = append(attrs, a.Key)
}
sort.Strings(attrs)
return
}

func getResourceAttribute(res types.Resource, key string) (val string) {
for _, attr := range res.Attributes {
if attr.Key == key {
Expand All @@ -84,8 +86,8 @@ func getResourceAttribute(res types.Resource, key string) (val string) {

func formatResource(res types.Resource) (out string) {
out = fmt.Sprintf("resource \"%s\" \"%s\" {\n", res.Type, res.Name)
for _, attr := range res.Attributes {
out += fmt.Sprintf(" %s = \"%s\"\n", attr.Key, attr.Value)
for _, attr := range resourceAttributes(res) {
out += fmt.Sprintf(" %s = \"%s\"\n", attr, getResourceAttribute(res, attr))
}
out += "}\n"

Expand Down Expand Up @@ -116,15 +118,15 @@ func compareResource(st1, st2 types.State, key string) (comp types.ResourceDiff)
}

// Compute unified diff
diff := difflib.ContextDiff{
diff := difflib.UnifiedDiff{
A: difflib.SplitLines(formatResource(res1)),
B: difflib.SplitLines(formatResource(res2)),
FromFile: stateInfo(st1),
ToFile: stateInfo(st2),
Context: 3,
Eol: "\n",
}
result, _ := difflib.GetContextDiffString(diff)
result, _ := difflib.GetUnifiedDiffString(diff)
comp.UnifiedDiff = result

return
Expand All @@ -137,8 +139,11 @@ func Compare(from, to types.State) (comp types.StateCompare, err error) {
}
fromResources := stateResources(from)
comp.Stats.From = types.StateInfo{
Path: from.Path,
VersionID: from.Version.VersionID,
ResourceCount: len(fromResources),
TFVersion: from.TFVersion,
Serial: from.Serial,
}

if to.Path == "" {
Expand All @@ -147,17 +152,33 @@ func Compare(from, to types.State) (comp types.StateCompare, err error) {
}
toResources := stateResources(to)
comp.Stats.To = types.StateInfo{
Path: to.Path,
VersionID: to.Version.VersionID,
ResourceCount: len(toResources),
TFVersion: to.TFVersion,
Serial: to.Serial,
}

// OnlyInOld
onlyInOld := sliceDiff(fromResources, toResources)
comp.Differences.OnlyInOld = make(map[string]string)
for _, r := range onlyInOld {
comp.Differences.OnlyInOld[r] = formatResource(getResource(from, r))
}

comp.Differences.OnlyInOld = sliceDiff(fromResources, toResources)
comp.Differences.OnlyInNew = sliceDiff(toResources, fromResources)
// OnlyInNew
onlyInNew := sliceDiff(toResources, fromResources)
comp.Differences.OnlyInNew = make(map[string]string)
for _, r := range onlyInNew {
comp.Differences.OnlyInNew[r] = formatResource(getResource(to, r))
}
comp.Differences.InBoth = sliceInter(toResources, fromResources)
comp.Differences.ResourceDiff = make(map[string]types.ResourceDiff)

for _, r := range comp.Differences.InBoth {
comp.Differences.ResourceDiff[r] = compareResource(to, from, r)
if c := compareResource(to, from, r); c.UnifiedDiff != "" {
comp.Differences.ResourceDiff[r] = c
}
}

log.WithFields(log.Fields{
Expand Down
90 changes: 90 additions & 0 deletions static/compare.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<div id="mainrow" class="row">
<div id="leftcol" class="col-md-4">
<div class="panel-group">
<div class="panel panel-info">
<div class="panel-heading">
<h4 class="panel-title">
From version
</h4>
</div>
<ul class="list-group">
<li class="list-group-item">Terraform version: {{compare.stats.from.terraform_version}}</li>
<li class="list-group-item">Serial: {{compare.stats.from.serial}}</li>
<li class="list-group-item">Version: <select class="form-control" ng-model="fromVersion" ng-options="version as version.date for version in versions track by version.versionId"></select></li>
<li class="list-group-item">Resource count: {{compare.stats.from.resource_count}}</li>
</ul>
</div>
<div class="panel panel-info">
<div class="panel-heading">
<h4 class="panel-title">
To version
</h4>
</div>
<ul class="list-group">
<li class="list-group-item">Terraform version: {{compare.stats.to.terraform_version}}</li>
<li class="list-group-item">Serial: {{compare.stats.to.serial}}</li>
<li class="list-group-item">Version: <select class="form-control" ng-model="toVersion" ng-options="version as version.date for version in versions track by version.versionId"></select></li>
<li class="list-group-item">Resource count: {{compare.stats.to.resource_count}}</li>
</ul>
</div>
</div>
</div>
<div id="node" class="col-md-8" ng-if="compare.differences">
<h2 class="node-title">{{compare.stats.from.path}}</h2>
<div class="panel-group">
<div class="panel panel-warning">
<div class="panel-heading">
<h4 id="panel-title-diff" class="panel-title">
<a data-toggle="collapse" data-target="#panel-body-diff">
Differences
</a>
<span id="badge-diff" class="badge">{{differences}}</span>
</h4>
</div>
<div id="panel-body-diff" class="panel-collapse collapse in">
<div class="panel-body">
<div class="list-group resource" ng-repeat="(resource, diff) in compare.differences.resource_diff">
<div class="resource-title">{{resource}}</div>
<hlcode lang="'diff'" code="diff.unified_diff"></hlcode>
</div>
</div>
</div>
</div>
<div class="panel panel-danger">
<div class="panel-heading">
<h4 id="panel-title-in-old" class="panel-title">
<a data-toggle="collapse" data-target="#panel-body-in-old">
Only in serial {{compare.stats.from.serial}}
</a>
<span id="badge-diff" class="badge">{{only_in_old}}</span>
</h4>
</div>
<div id="panel-body-in-old" class="panel-collapse collapse in">
<div class="panel-body">
<div class="list-group resource" ng-repeat="(resource, code) in compare.differences.only_in_old">
<div class="resource-title">{{resource}}</div>
<hlcode lang="'ruby'" code="code"></hlcode>
</div>
</div>
</div>
</div>
<div class="panel panel-success">
<div class="panel-heading">
<h4 id="panel-title-in-new" class="panel-title">
<a data-toggle="collapse" data-target="#panel-body-in-new">
Only in serial {{compare.stats.to.serial}}
</a>
<span id="badge-diff" class="badge">{{only_in_new}}</span>
</h4>
</div>
<div id="panel-body-in-new" class="panel-collapse collapse in">
<div class="panel-body">
<div class="list-group resource" ng-repeat="(resource, code) in compare.differences.only_in_new">
<div class="resource-title">{{resource}}</div>
<hlcode lang="'ruby'" code="code"></hlcode>
</div>
</div>
</div>
</div>
</div>
</div>
5 changes: 5 additions & 0 deletions static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@

<script src="static/select.min.js" type="text/javascript"></script>
<script src="static/terraboard.js" type="text/javascript"></script>

<script src="static/sh_main.min.js" type="text/javascript"></script>
<script src="static/sh_diff.js" type="text/javascript"></script>
<script src="static/sh_ruby.min.js" type="text/javascript"></script>
<link href="static/sh_style.css" rel="stylesheet" type="text/css">
</head>

<body ng-app="terraboard">
Expand Down
122 changes: 122 additions & 0 deletions static/sh_diff.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
if (! this.sh_languages) {
this.sh_languages = {};
}
sh_languages['diff'] = [
[
[
/(?=^[-]{3})/g,
'sh_oldfile',
1,
1
],
[
/(?=^[*]{3})/g,
'sh_oldfile',
3,
1
],
[
/(?=^[\d])/g,
'sh_difflines',
6,
1
]
],
[
[
/^[-]{3}/g,
'sh_oldfile',
2
],
[
/^[-]/g,
'sh_oldfile',
2
],
[
/^[+]/g,
'sh_newfile',
2
],
[
/^@@/g,
'sh_difflines',
2
]
],
[
[
/$/g,
null,
-2
]
],
[
[
/^[*]{3}[ \t]+[\d]/g,
'sh_oldfile',
4
],
[
/^[*]{3}/g,
'sh_oldfile',
2
],
[
/^[-]{3}[ \t]+[\d]/g,
'sh_newfile',
5
],
[
/^[-]{3}/g,
'sh_newfile',
2
]
],
[
[
/^[\s]/g,
'sh_normal',
2
],
[
/(?=^[-]{3})/g,
'sh_newfile',
-2
]
],
[
[
/^[\s]/g,
'sh_normal',
2
],
[
/(?=^[*]{3})/g,
'sh_newfile',
-2
],
[
/^diff/g,
'sh_normal',
2
]
],
[
[
/^[\d]/g,
'sh_difflines',
2
],
[
/^[<]/g,
'sh_oldfile',
2
],
[
/^[>]/g,
'sh_newfile',
2
]
]
];
4 changes: 4 additions & 0 deletions static/sh_main.min.js

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

1 change: 1 addition & 0 deletions static/sh_ruby.min.js

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

Loading

0 comments on commit 7192158

Please sign in to comment.