Skip to content

Commit

Permalink
Add support for multiple instances of the same resource, for count an…
Browse files Browse the repository at this point in the history
…d for_each cases (#115)

Co-authored-by: Victor Cabezas <vcabezas@tuenti.com>
  • Loading branch information
Wiston999 and Victor Cabezas authored Oct 1, 2020
1 parent a7ada9f commit 5906197
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 13 deletions.
30 changes: 20 additions & 10 deletions db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/camptocamp/terraboard/config"
"github.com/camptocamp/terraboard/state"
"github.com/camptocamp/terraboard/types"
"github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/states/statefile"
log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -62,22 +63,31 @@ func (db *Database) stateS3toDB(sf *statefile.File, path string, versionID strin
Path: m.Addr.String(),
}
for _, r := range m.Resources {
res := types.Resource{
Type: r.Addr.Resource.Type,
Name: r.Addr.Resource.Name,
for index, i := range r.Instances {
res := types.Resource{
Type: r.Addr.Resource.Type,
Name: r.Addr.Resource.Name,
Index: getResourceIndex(index),
Attributes: marshalAttributeValues(i.Current),
}
mod.Resources = append(mod.Resources, res)
}

for _, i := range r.Instances {
res.Attributes = marshalAttributeValues(i.Current)
}

mod.Resources = append(mod.Resources, res)
}
st.Modules = append(st.Modules, mod)
}
return
}

// getResourceIndex transforms an addrs.InstanceKey instance into a string representation
func getResourceIndex(index addrs.InstanceKey) string {
switch index.(type) {
case addrs.IntKey, addrs.StringKey:
return index.String()
}
return ""
}

func marshalAttributeValues(src *states.ResourceInstanceObjectSrc) (attrs []types.Attribute) {
vals := make(attributeValues)
if src.AttrsFlat != nil {
Expand Down Expand Up @@ -232,9 +242,9 @@ func (db *Database) SearchAttribute(query url.Values) (results []types.SearchRes

// Now get results
// gorm doesn't support subqueries...
sql := "SELECT states.path, states.version_id, states.tf_version, states.serial, modules.path as module_path, resources.type, resources.name, attributes.key, attributes.value" +
sql := "SELECT states.path, states.version_id, states.tf_version, states.serial, modules.path as module_path, resources.type, resources.name, resources.index, attributes.key, attributes.value" +
sqlQuery +
" ORDER BY states.path, states.serial, modules.path, resources.type, resources.name, attributes.key" +
" ORDER BY states.path, states.serial, modules.path, resources.type, resources.name, resources.index, attributes.key" +
" LIMIT ?"

params = append(params, pageSize)
Expand Down
9 changes: 9 additions & 0 deletions state/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ func (a *AWS) GetLocks() (locks map[string]LockInfo, err error) {

// GetStates returns a slice of State files in the S3 bucket
func (a *AWS) GetStates() (states []string, err error) {
log.WithFields(log.Fields{
"bucket": a.bucket,
"prefix": a.keyPrefix,
}).Debug("Listing states from S3")
result, err := a.svc.ListObjects(&s3.ListObjectsInput{
Bucket: aws_sdk.String(a.bucket),
Prefix: &a.keyPrefix,
Expand All @@ -106,6 +110,11 @@ func (a *AWS) GetStates() (states []string, err error) {
}
}
states = keys
log.WithFields(log.Fields{
"bucket": a.bucket,
"prefix": a.keyPrefix,
"states": len(states),
}).Debug("Found states from S3")
return states, nil
}

Expand Down
2 changes: 1 addition & 1 deletion static/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
<td>{{r.tf_version}}</td>
<td>{{r.serial}}</td>
<td>{{r.module_path}}</td>
<td>{{r.resource_name}}</td>
<td>{{r.resource_type}}.{{r.resource_name}}{{r.resource_index}}</td>
<td>{{r.attribute_key}}</td>
<td class="attr-val">{{r.attribute_value}}</td>
</tr>
Expand Down
4 changes: 2 additions & 2 deletions static/state.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ <h4>{{mod.path}}</h4>
<li ng-repeat="r in mod.resources | filter:{name:resFilter} as filteredRes"
ng-class="{selected: r == selectedres}"
ng-click="setSelected(mod, r)" class="list-group-item resource">
{{r.type}}.{{r.name}}
{{r.type}}.{{r.name}}{{r.index}}
</li>
</ul>
</li>
Expand All @@ -62,7 +62,7 @@ <h1>{{path}}</h1>
</div>
<!-- Resource details view -->
<div class="row" ng-if="display.details && selectedres">
<h2 class="node-title">{{selectedres.type}}.{{selectedres.name}}</h2>
<h2 class="node-title">{{selectedres.type}}.{{selectedres.name}}{{selectedres.index}}</h2>
<div class="panel-group">
<div class="panel panel-info">
<div class="panel-heading">
Expand Down
1 change: 1 addition & 0 deletions types/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type Resource struct {
ModuleID sql.NullInt64 `gorm:"index" json:"-"`
Type string `gorm:"index" json:"type"`
Name string `gorm:"index" json:"name"`
Index string `gorm:"index" json:"index"`
Attributes []Attribute `json:"attributes"`
}

Expand Down
1 change: 1 addition & 0 deletions types/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type SearchResult struct {
ModulePath string `gorm:"column:module_path" json:"module_path"`
ResourceType string `gorm:"column:type" json:"resource_type"`
ResourceName string `gorm:"column:name" json:"resource_name"`
ResourceIndex string `gorm:"column:index" json:"resource_index"`
AttributeKey string `gorm:"column:key" json:"attribute_key"`
AttributeValue string `gorm:"column:value" json:"attribute_value"`
}
Expand Down

0 comments on commit 5906197

Please sign in to comment.