2021-03-26 08:44:55 +00:00
|
|
|
package resource
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
|
2021-06-09 15:28:40 +00:00
|
|
|
"github.com/hashicorp/go-version"
|
2021-03-26 08:44:55 +00:00
|
|
|
"github.com/hashicorp/terraform/configs/configschema"
|
|
|
|
"github.com/hashicorp/terraform/providers"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
type AttributeSchema struct {
|
|
|
|
ConfigSchema configschema.Attribute
|
|
|
|
JsonString bool
|
|
|
|
}
|
|
|
|
|
2021-09-17 15:16:06 +00:00
|
|
|
type Flags uint32
|
|
|
|
|
|
|
|
const (
|
|
|
|
FlagDeepMode Flags = 1 << iota
|
|
|
|
)
|
|
|
|
|
|
|
|
func (f Flags) HasFlag(flag Flags) bool {
|
|
|
|
return f&flag != 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *Flags) AddFlag(flag Flags) {
|
|
|
|
*f |= flag
|
|
|
|
}
|
|
|
|
|
2021-03-26 08:44:55 +00:00
|
|
|
type Schema struct {
|
2021-06-09 15:28:40 +00:00
|
|
|
ProviderVersion *version.Version
|
2021-09-17 15:16:06 +00:00
|
|
|
Flags Flags
|
2021-06-09 15:28:40 +00:00
|
|
|
SchemaVersion int64
|
2021-05-21 14:09:45 +00:00
|
|
|
Attributes map[string]AttributeSchema
|
2021-08-09 14:03:04 +00:00
|
|
|
NormalizeFunc func(res *Resource)
|
|
|
|
HumanReadableAttributesFunc func(res *Resource) map[string]string
|
|
|
|
ResolveReadAttributesFunc func(res *Resource) map[string]string
|
2021-10-15 14:52:22 +00:00
|
|
|
DiscriminantFunc func(*Resource, *Resource) bool
|
2021-03-26 08:44:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Schema) IsComputedField(path []string) bool {
|
|
|
|
metadata, exist := s.Attributes[strings.Join(path, ".")]
|
|
|
|
if !exist {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return metadata.ConfigSchema.Computed
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Schema) IsJsonStringField(path []string) bool {
|
|
|
|
metadata, exist := s.Attributes[strings.Join(path, ".")]
|
|
|
|
if !exist {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return metadata.JsonString
|
|
|
|
}
|
|
|
|
|
|
|
|
type SchemaRepositoryInterface interface {
|
|
|
|
GetSchema(resourceType string) (*Schema, bool)
|
2021-09-17 15:16:06 +00:00
|
|
|
SetFlags(typ string, flags ...Flags)
|
2021-03-26 08:44:55 +00:00
|
|
|
UpdateSchema(typ string, schemasMutators map[string]func(attributeSchema *AttributeSchema))
|
2021-08-09 14:03:04 +00:00
|
|
|
SetNormalizeFunc(typ string, normalizeFunc func(res *Resource))
|
|
|
|
SetHumanReadableAttributesFunc(typ string, humanReadableAttributesFunc func(res *Resource) map[string]string)
|
|
|
|
SetResolveReadAttributesFunc(typ string, resolveReadAttributesFunc func(res *Resource) map[string]string)
|
2021-10-15 14:52:22 +00:00
|
|
|
SetDiscriminantFunc(string, func(*Resource, *Resource) bool)
|
2021-03-26 08:44:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type SchemaRepository struct {
|
2021-06-17 12:15:45 +00:00
|
|
|
schemas map[string]*Schema
|
2021-07-29 09:50:35 +00:00
|
|
|
ProviderName string
|
2021-06-17 12:15:45 +00:00
|
|
|
ProviderVersion *version.Version
|
2021-03-26 08:44:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewSchemaRepository() *SchemaRepository {
|
|
|
|
return &SchemaRepository{
|
|
|
|
schemas: make(map[string]*Schema),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *SchemaRepository) GetSchema(resourceType string) (*Schema, bool) {
|
|
|
|
schema, exist := r.schemas[resourceType]
|
|
|
|
return schema, exist
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *SchemaRepository) fetchNestedBlocks(root string, metadata map[string]AttributeSchema, block map[string]*configschema.NestedBlock) {
|
|
|
|
for s, nestedBlock := range block {
|
|
|
|
path := s
|
|
|
|
if root != "" {
|
|
|
|
path = strings.Join([]string{root, s}, ".")
|
|
|
|
}
|
|
|
|
for s2, attr := range nestedBlock.Attributes {
|
|
|
|
nestedPath := strings.Join([]string{path, s2}, ".")
|
|
|
|
metadata[nestedPath] = AttributeSchema{
|
|
|
|
ConfigSchema: *attr,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r.fetchNestedBlocks(path, metadata, nestedBlock.BlockTypes)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-29 09:50:35 +00:00
|
|
|
func (r *SchemaRepository) Init(providerName, providerVersion string, schema map[string]providers.Schema) error {
|
|
|
|
v, err := version.NewVersion(providerVersion)
|
2021-06-09 15:28:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-07-29 09:50:35 +00:00
|
|
|
r.ProviderVersion = v
|
|
|
|
r.ProviderName = providerName
|
2021-03-26 08:44:55 +00:00
|
|
|
for typ, sch := range schema {
|
|
|
|
attributeMetas := map[string]AttributeSchema{}
|
|
|
|
for s, attribute := range sch.Block.Attributes {
|
|
|
|
attributeMetas[s] = AttributeSchema{
|
|
|
|
ConfigSchema: *attribute,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r.fetchNestedBlocks("", attributeMetas, sch.Block.BlockTypes)
|
|
|
|
|
|
|
|
r.schemas[typ] = &Schema{
|
2021-06-17 12:15:45 +00:00
|
|
|
ProviderVersion: r.ProviderVersion,
|
2021-06-09 15:28:40 +00:00
|
|
|
SchemaVersion: sch.Version,
|
|
|
|
Attributes: attributeMetas,
|
2021-03-26 08:44:55 +00:00
|
|
|
}
|
|
|
|
}
|
2021-06-09 15:28:40 +00:00
|
|
|
return nil
|
2021-03-26 08:44:55 +00:00
|
|
|
}
|
|
|
|
|
2021-09-17 15:16:06 +00:00
|
|
|
func (r SchemaRepository) SetFlags(typ string, flags ...Flags) {
|
|
|
|
metadata, exist := r.GetSchema(typ)
|
|
|
|
if !exist {
|
|
|
|
logrus.WithFields(logrus.Fields{"type": typ}).Warning("Unable to set flags, no schema found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, flag := range flags {
|
|
|
|
metadata.Flags.AddFlag(flag)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-26 08:44:55 +00:00
|
|
|
func (r *SchemaRepository) UpdateSchema(typ string, schemasMutators map[string]func(attributeSchema *AttributeSchema)) {
|
|
|
|
for s, f := range schemasMutators {
|
|
|
|
metadata, exist := r.GetSchema(typ)
|
|
|
|
if !exist {
|
|
|
|
logrus.WithFields(logrus.Fields{"type": typ}).Warning("Unable to set metadata, no schema found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
m := (*metadata).Attributes[s]
|
|
|
|
f(&m)
|
|
|
|
(*metadata).Attributes[s] = m
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-09 14:03:04 +00:00
|
|
|
func (r *SchemaRepository) SetNormalizeFunc(typ string, normalizeFunc func(res *Resource)) {
|
2021-03-26 08:44:55 +00:00
|
|
|
metadata, exist := r.GetSchema(typ)
|
|
|
|
if !exist {
|
|
|
|
logrus.WithFields(logrus.Fields{"type": typ}).Warning("Unable to set normalize func, no schema found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
(*metadata).NormalizeFunc = normalizeFunc
|
|
|
|
}
|
2021-05-21 14:09:45 +00:00
|
|
|
|
2021-08-09 14:03:04 +00:00
|
|
|
func (r *SchemaRepository) SetHumanReadableAttributesFunc(typ string, humanReadableAttributesFunc func(res *Resource) map[string]string) {
|
2021-05-21 14:09:45 +00:00
|
|
|
metadata, exist := r.GetSchema(typ)
|
|
|
|
if !exist {
|
|
|
|
logrus.WithFields(logrus.Fields{"type": typ}).Warning("Unable to add human readable attributes, no schema found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
(*metadata).HumanReadableAttributesFunc = humanReadableAttributesFunc
|
|
|
|
}
|
2021-08-03 16:02:36 +00:00
|
|
|
|
2021-08-09 14:03:04 +00:00
|
|
|
func (r *SchemaRepository) SetResolveReadAttributesFunc(typ string, resolveReadAttributesFunc func(res *Resource) map[string]string) {
|
2021-08-03 16:02:36 +00:00
|
|
|
metadata, exist := r.GetSchema(typ)
|
|
|
|
if !exist {
|
|
|
|
logrus.WithFields(logrus.Fields{"type": typ}).Warning("Unable to add read resource attributes, no schema found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
(*metadata).ResolveReadAttributesFunc = resolveReadAttributesFunc
|
|
|
|
}
|
2021-10-15 14:52:22 +00:00
|
|
|
|
|
|
|
func (r *SchemaRepository) SetDiscriminantFunc(typ string, fn func(self, res *Resource) bool) {
|
|
|
|
metadata, exist := r.GetSchema(typ)
|
|
|
|
if !exist {
|
|
|
|
logrus.WithFields(logrus.Fields{"type": typ}).Warning("Unable to set discriminant function, no schema found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
(*metadata).DiscriminantFunc = fn
|
|
|
|
}
|