178 lines
4.1 KiB
Go
178 lines
4.1 KiB
Go
package mocks
|
|
|
|
import (
|
|
gojson "encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"sort"
|
|
|
|
"github.com/snyk/driftctl/test/goldenfile"
|
|
|
|
"github.com/hashicorp/terraform/providers"
|
|
"github.com/snyk/driftctl/pkg/terraform"
|
|
"github.com/zclconf/go-cty/cty"
|
|
ctyjson "github.com/zclconf/go-cty/cty/json"
|
|
)
|
|
|
|
type MockedGoldenTFProvider struct {
|
|
name string
|
|
realProvider terraform.TerraformProvider
|
|
update bool
|
|
}
|
|
|
|
func NewMockedGoldenTFProvider(name string, realProvider terraform.TerraformProvider, update bool) *MockedGoldenTFProvider {
|
|
return &MockedGoldenTFProvider{name: name, realProvider: realProvider, update: update}
|
|
}
|
|
|
|
func (m *MockedGoldenTFProvider) Schema() map[string]providers.Schema {
|
|
if m.update {
|
|
schema := m.realProvider.Schema()
|
|
m.writeSchema(schema)
|
|
return schema
|
|
}
|
|
return m.readSchema()
|
|
}
|
|
|
|
func (m *MockedGoldenTFProvider) ReadResource(args terraform.ReadResourceArgs) (*cty.Value, error) {
|
|
if m.update {
|
|
readResource, err := m.realProvider.ReadResource(args)
|
|
m.writeReadResource(args, readResource, err)
|
|
return readResource, err
|
|
}
|
|
|
|
return m.readReadResource(args)
|
|
}
|
|
|
|
func (m *MockedGoldenTFProvider) writeSchema(schema map[string]providers.Schema) {
|
|
marshal, err := gojson.Marshal(schema)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
goldenfile.WriteFile(m.name, marshal, "schema.golden.json")
|
|
}
|
|
|
|
func (m *MockedGoldenTFProvider) readSchema() map[string]providers.Schema {
|
|
content := goldenfile.ReadFile(m.name, "schema.golden.json")
|
|
var schema map[string]providers.Schema
|
|
if err := gojson.Unmarshal(content, &schema); err != nil {
|
|
panic(err)
|
|
}
|
|
return schema
|
|
}
|
|
|
|
func (m *MockedGoldenTFProvider) writeReadResource(args terraform.ReadResourceArgs, readResource *cty.Value, err error) {
|
|
var readRes = ReadResource{
|
|
Value: readResource,
|
|
Err: err,
|
|
}
|
|
|
|
marshalled, err := gojson.Marshal(&readRes)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
fileName := getFileName(args)
|
|
goldenfile.WriteFile(m.name, marshalled, fileName)
|
|
}
|
|
|
|
func (m *MockedGoldenTFProvider) readReadResource(args terraform.ReadResourceArgs) (*cty.Value, error) {
|
|
fileName := getFileName(args)
|
|
// TODO I'm putting this here for compatibility reason...
|
|
if !goldenfile.FileExists(m.name, fileName) {
|
|
fileName = fmt.Sprintf("%s-%s.res.golden.json", args.Ty, args.ID)
|
|
}
|
|
|
|
content := goldenfile.ReadFile(m.name, fileName)
|
|
var readRes ReadResource
|
|
if err := gojson.Unmarshal(content, &readRes); err != nil {
|
|
panic(err)
|
|
}
|
|
return readRes.Value, readRes.Err
|
|
}
|
|
|
|
type ReadResource struct {
|
|
Value *cty.Value
|
|
Err error
|
|
}
|
|
|
|
func (m *ReadResource) UnmarshalJSON(bytes []byte) error {
|
|
var unm struct {
|
|
Typ []byte
|
|
Val []byte
|
|
Err *string
|
|
}
|
|
if err := gojson.Unmarshal(bytes, &unm); err != nil {
|
|
return err
|
|
}
|
|
if unm.Typ != nil {
|
|
unmarshalType, err := ctyjson.UnmarshalType(unm.Typ)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if unm.Val != nil {
|
|
unmarshal, err := ctyjson.Unmarshal(unm.Val, unmarshalType)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
m.Value = &unmarshal
|
|
}
|
|
}
|
|
if unm.Err != nil {
|
|
m.Err = errors.New(*unm.Err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *ReadResource) MarshalJSON() ([]byte, error) {
|
|
var unm struct {
|
|
Typ []byte
|
|
Val []byte
|
|
Err *string
|
|
}
|
|
if m.Value != nil {
|
|
var err error
|
|
unm.Typ, err = ctyjson.MarshalType(m.Value.Type())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
unm.Val, err = ctyjson.Marshal(*m.Value, m.Value.Type())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
if m.Err != nil {
|
|
e := m.Err.Error()
|
|
unm.Err = &e
|
|
}
|
|
return gojson.Marshal(unm)
|
|
}
|
|
|
|
func getFileName(args terraform.ReadResourceArgs) string {
|
|
suffix := getFileNameSuffix(args)
|
|
fileName := fmt.Sprintf("%s-%s%s.res.golden.json", args.Ty, args.ID, suffix)
|
|
return fileName
|
|
}
|
|
|
|
func getFileNameSuffix(args terraform.ReadResourceArgs) string {
|
|
suffix := ""
|
|
keys := make([]string, 0, len(args.Attributes))
|
|
for k := range args.Attributes {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
|
|
for _, k := range keys {
|
|
suffix = fmt.Sprintf("%s-%s", suffix, args.Attributes[k])
|
|
}
|
|
return suffix
|
|
}
|
|
|
|
func (p MockedGoldenTFProvider) Cleanup() {}
|
|
|
|
func (p *MockedGoldenTFProvider) Name() string {
|
|
return p.realProvider.Name()
|
|
}
|
|
|
|
func (p *MockedGoldenTFProvider) Version() string {
|
|
return p.realProvider.Version()
|
|
}
|