This commit is contained in:
Mustafa Gezen 2023-08-25 20:30:36 +02:00
parent dd9bdf3ed2
commit 67a3ae6145
Signed by: mustafa
GPG Key ID: DCDF010D946438C1
2520 changed files with 1320846 additions and 1571515 deletions

1
base/go/fs.go Normal file
View File

@ -0,0 +1 @@
package base

717
deps.bzl

File diff suppressed because it is too large Load Diff

185
go.mod
View File

@ -4,8 +4,9 @@ go 1.20
replace (
github.com/coreos/bbolt v1.3.7 => go.etcd.io/bbolt v1.3.7
// this is due to temporalite
github.com/grpc-ecosystem/grpc-gateway => github.com/temporalio/grpc-gateway v1.17.0
github.com/smartystreets/assertions v1.15.1 => github.com/smarty/assertions v1.15.1
go.opentelemetry.io/otel/metric => go.opentelemetry.io/otel/metric v0.30.0
)
require (
@ -17,11 +18,12 @@ require (
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.2
github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.1
github.com/prometheus/client_golang v1.16.0
github.com/temporalio/temporalite v0.3.0
github.com/testcontainers/testcontainers-go v0.23.0
github.com/testcontainers/testcontainers-go/modules/postgres v0.23.0
github.com/stretchr/testify v1.8.4
github.com/temporalio/temporalite v0.3.1-0.20230117200252-2df426ad3426
github.com/testcontainers/testcontainers-go v0.21.0
github.com/testcontainers/testcontainers-go/modules/postgres v0.21.0
github.com/urfave/cli/v2 v2.25.7
github.com/wk8/go-ordered-map/v2 v2.1.8
go.ciq.dev/pika v0.0.0-20230819201750-737c3e8f413d
@ -29,52 +31,51 @@ require (
go.resf.org/peridot/tools/mothership/admin/pb v0.0.0-00010101000000-000000000000
go.resf.org/peridot/tools/mothership/pb v0.0.0-00010101000000-000000000000
go.starlark.net v0.0.0-20230814145427-12f4cb8177e4
golang.org/x/mod v0.10.0
golang.org/x/oauth2 v0.10.0
google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5
golang.org/x/mod v0.12.0
golang.org/x/oauth2 v0.11.0
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d
google.golang.org/grpc v1.57.0
google.golang.org/protobuf v1.31.0
k8s.io/api v0.28.0
k8s.io/apimachinery v0.28.0
k8s.io/cli-runtime v0.28.0
k8s.io/api v0.28.1
k8s.io/apimachinery v0.28.1
k8s.io/cli-runtime v0.28.1
)
require (
ariga.io/atlas v0.10.2-0.20230427182402-87a07dfb83bf // indirect
ariga.io/atlas v0.13.2 // indirect
bitbucket.org/creachadair/stringset v0.0.11 // indirect
cloud.google.com/go v0.110.6 // indirect
cloud.google.com/go v0.110.7 // indirect
cloud.google.com/go/compute v1.23.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v1.1.1 // indirect
cloud.google.com/go/iam v1.1.2 // indirect
cloud.google.com/go/longrunning v0.5.1 // indirect
cloud.google.com/go/storage v1.30.1 // indirect
dario.cat/mergo v1.0.0 // indirect
cloud.google.com/go/storage v1.32.0 // indirect
entgo.io/ent v0.12.3 // indirect
github.com/AppsFlyer/go-sundheit v0.5.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/semver/v3 v3.2.0 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/agext/levenshtein v1.2.1 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9 // indirect
github.com/apache/thrift v0.16.0 // indirect
github.com/apache/thrift v0.18.1 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/aws/aws-sdk-go v1.44.41 // indirect
github.com/aws/aws-sdk-go v1.44.331 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/beevik/etree v1.2.0 // indirect
github.com/benbjohnson/clock v1.3.0 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/bmatcuk/doublestar/v4 v4.6.0 // indirect
github.com/bufbuild/protocompile v0.4.0 // indirect
github.com/bufbuild/protocompile v0.6.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/cactus/go-statsd-client/statsd v0.0.0-20200423205355-cb0885a1018c // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/containerd/containerd v1.7.3 // indirect
github.com/containerd/containerd v1.7.0-beta.0 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpuguy83/dockercfg v0.3.1 // indirect
@ -86,6 +87,7 @@ require (
github.com/docker/docker v24.0.5+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/fsnotify/fsevents v0.1.1 // indirect
@ -99,22 +101,22 @@ require (
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/inflect v0.19.0 // indirect
github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/gocql/gocql v1.2.0 // indirect
github.com/gocql/gocql v1.5.2 // indirect
github.com/gogo/gateway v1.1.0 // indirect
github.com/gogo/googleapis v1.4.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/gogo/status v1.1.1 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
github.com/golang/glog v1.1.0 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/glog v1.1.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/mock v1.7.0-rc.1 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/s2a-go v0.1.4 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/google/s2a-go v0.1.5 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/gopherjs/gopherjs v1.17.2 // indirect
@ -124,37 +126,37 @@ require (
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
github.com/hashicorp/hcl/v2 v2.13.0 // indirect
github.com/huandu/xstrings v1.3.3 // indirect
github.com/hashicorp/hcl/v2 v2.17.0 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/iancoleman/strcase v0.3.0 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jaschaephraim/lrserver v0.0.0-20171129202958-50d19f603f71 // indirect
github.com/jhump/protoreflect v1.15.1 // indirect
github.com/jhump/protoreflect v1.15.2 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jmoiron/sqlx v1.3.5 // indirect
github.com/jonboulle/clockwork v0.3.0 // indirect
github.com/jonboulle/clockwork v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/jtolds/gls v4.20.0+incompatible // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/klauspost/compress v1.16.0 // indirect
github.com/labstack/echo/v4 v4.9.1 // indirect
github.com/labstack/echo/v4 v4.11.1 // indirect
github.com/labstack/gommon v0.4.0 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect
github.com/mattn/go-sqlite3 v1.14.17 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
github.com/mitchellh/reflectwalk v1.0.0 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/patternmatcher v0.5.0 // indirect
github.com/moby/sys/sequential v0.5.0 // indirect
github.com/moby/term v0.5.0 // indirect
@ -171,63 +173,60 @@ require (
github.com/pborman/uuid v1.2.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/robfig/cron v1.2.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/russellhaering/goxmldsig v1.4.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smarty/assertions v1.15.1 // indirect
github.com/smartystreets/assertions v1.15.1 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/cobra v1.7.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stoewer/go-strcase v1.3.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/stretchr/testify v1.8.4 // indirect
github.com/temporalio/ringpop-go v0.0.0-20220818230611-30bf23b490b2 // indirect
github.com/stretchr/objx v0.5.1 // indirect
github.com/temporalio/ringpop-go v0.0.0-20230606200434-b5c079f412d3 // indirect
github.com/temporalio/tchannel-go v1.22.1-0.20220818200552-1be8d8cffa5b // indirect
github.com/temporalio/ui-server/v2 v2.8.3 // indirect
github.com/twmb/murmur3 v1.1.6 // indirect
github.com/temporalio/ui-server/v2 v2.11.1 // indirect
github.com/twmb/murmur3 v1.1.8 // indirect
github.com/uber-common/bark v1.3.0 // indirect
github.com/uber-go/tally/v4 v4.1.2 // indirect
github.com/uber-go/tally/v4 v4.1.6 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.1 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 // indirect
github.com/zclconf/go-cty v1.8.0 // indirect
github.com/zclconf/go-cty v1.13.3 // indirect
go.etcd.io/etcd/api/v3 v3.5.9 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect
go.etcd.io/etcd/client/v3 v3.5.9 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.40.0 // indirect
go.opentelemetry.io/otel v1.14.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.36.2 // indirect
go.opentelemetry.io/otel v1.10.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.14.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.30.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.30.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.14.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.14.0 // indirect
go.opentelemetry.io/otel/exporters/prometheus v0.30.0 // indirect
go.opentelemetry.io/otel/metric v0.37.0 // indirect
go.opentelemetry.io/otel/sdk v1.14.0 // indirect
go.opentelemetry.io/otel/sdk/metric v0.30.0 // indirect
go.opentelemetry.io/otel/trace v1.14.0 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.temporal.io/api v1.12.0 // indirect
go.temporal.io/sdk v1.17.0 // indirect
go.temporal.io/server v1.18.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.31.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.31.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0 // indirect
go.opentelemetry.io/otel/exporters/prometheus v0.31.0 // indirect
go.opentelemetry.io/otel/metric v0.32.2 // indirect
go.opentelemetry.io/otel/sdk v1.10.0 // indirect
go.opentelemetry.io/otel/sdk/metric v0.31.0 // indirect
go.opentelemetry.io/otel/trace v1.10.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.temporal.io/api v1.13.1-0.20221110200459-6a3cb21a3415 // indirect
go.temporal.io/sdk v1.19.0 // indirect
go.temporal.io/server v1.19.1 // indirect
go.temporal.io/version v0.3.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/dig v1.14.1 // indirect
go.uber.org/fx v1.17.1 // indirect
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.23.0 // indirect
go.uber.org/dig v1.16.1 // indirect
go.uber.org/fx v1.19.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.25.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
golang.org/x/net v0.14.0 // indirect
@ -235,32 +234,32 @@ require (
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.8.1-0.20230428195545-5283a0178901 // indirect
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.134.0 // indirect
google.golang.org/api v0.138.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230807174057-1744710a1577 // indirect
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/validator.v2 v2.0.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/client-go v0.28.0 // indirect
k8s.io/client-go v0.28.1 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/cc/v3 v3.36.0 // indirect
modernc.org/ccgo/v3 v3.16.6 // indirect
modernc.org/libc v1.16.10 // indirect
modernc.org/mathutil v1.4.1 // indirect
modernc.org/memory v1.1.1 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
lukechampine.com/uint128 v1.3.0 // indirect
modernc.org/cc/v3 v3.40.0 // indirect
modernc.org/ccgo/v3 v3.16.13 // indirect
modernc.org/libc v1.22.3 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.5.0 // indirect
modernc.org/opt v0.1.3 // indirect
modernc.org/sqlite v1.17.3 // indirect
modernc.org/strutil v1.1.2 // indirect
modernc.org/token v1.0.0 // indirect
modernc.org/sqlite v1.21.0 // indirect
modernc.org/strutil v1.1.3 // indirect
modernc.org/token v1.1.0 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

785
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
package mothershipadmin_rpc

View File

@ -5,8 +5,7 @@ go_library(
srcs = [
"context.go",
"extension.go",
"hcl.go",
"opts.go",
"schemahcl.go",
"spec.go",
"stdlib.go",
"types.go",
@ -28,5 +27,6 @@ go_library(
"//vendor/github.com/zclconf/go-cty/cty/function",
"//vendor/github.com/zclconf/go-cty/cty/function/stdlib",
"//vendor/github.com/zclconf/go-cty/cty/gocty",
"//vendor/github.com/zclconf/go-cty/cty/json",
],
)

View File

@ -72,7 +72,7 @@ func (s *State) setInputVals(ctx *hcl.EvalContext, body hcl.Body, input map[stri
return nil
}
// evalReferences evaluates data blocks.
// evalReferences evaluates local and data blocks.
func (s *State) evalReferences(ctx *hcl.EvalContext, body *hclsyntax.Body) error {
type node struct {
addr [3]string
@ -86,7 +86,7 @@ func (s *State) evalReferences(ctx *hcl.EvalContext, body *hclsyntax.Body) error
)
for _, b := range body.Blocks {
switch b := b; {
case b.Type == dataBlock:
case b.Type == BlockData:
if len(b.Labels) < 2 {
return fmt.Errorf("data block %q must have exactly 2 labels", b.Type)
}
@ -96,18 +96,18 @@ func (s *State) evalReferences(ctx *hcl.EvalContext, body *hclsyntax.Body) error
}
// Data references are combined from
// "data", "source" and "name" labels.
addr := [3]string{dataBlock, b.Labels[0], b.Labels[1]}
addr := [3]string{RefData, b.Labels[0], b.Labels[1]}
nodes[addr] = &node{
addr: addr,
value: func() (cty.Value, error) { return h(ctx, b) },
edges: func() []hcl.Traversal { return bodyVars(b.Body) },
}
case b.Type == localsBlock:
case b.Type == BlockLocals:
for k, v := range b.Body.Attributes {
k, v := k, v
// Local references are combined from
// "local" and "name" labels.
addr := [3]string{localRef, k, ""}
addr := [3]string{RefLocal, k, ""}
nodes[addr] = &node{
addr: addr,
edges: func() []hcl.Traversal { return hclsyntax.Variables(v.Expr) },
@ -141,7 +141,7 @@ func (s *State) evalReferences(ctx *hcl.EvalContext, body *hclsyntax.Body) error
}
}
var (
visit func(n *node) error
visit func(*node) error
visited = make(map[*node]bool)
progress = make(map[*node]bool)
)
@ -160,10 +160,10 @@ func (s *State) evalReferences(ctx *hcl.EvalContext, body *hclsyntax.Body) error
for _, e := range n.edges() {
var addr [3]string
switch root := e.RootName(); {
case root == localRef && len(e) == 2:
addr = [3]string{localRef, e[1].(hcl.TraverseAttr).Name, ""}
case root == dataBlock && len(e) > 2:
addr = [3]string{dataBlock, e[1].(hcl.TraverseAttr).Name, e[2].(hcl.TraverseAttr).Name}
case root == RefLocal && len(e) > 1:
addr = [3]string{RefLocal, e[1].(hcl.TraverseAttr).Name, ""}
case root == RefData && len(e) > 2:
addr = [3]string{RefData, e[1].(hcl.TraverseAttr).Name, e[2].(hcl.TraverseAttr).Name}
case s.config.initblk[root] != nil && len(e) == 1:
addr = [3]string{root, "", ""}
}
@ -181,9 +181,9 @@ func (s *State) evalReferences(ctx *hcl.EvalContext, body *hclsyntax.Body) error
return err
}
switch n.addr[0] {
case dataBlock:
case RefData:
data := make(map[string]cty.Value)
if vv, ok := ctx.Variables[dataBlock]; ok {
if vv, ok := ctx.Variables[RefData]; ok {
data = vv.AsValueMap()
}
src := make(map[string]cty.Value)
@ -192,14 +192,14 @@ func (s *State) evalReferences(ctx *hcl.EvalContext, body *hclsyntax.Body) error
}
src[n.addr[2]] = v
data[n.addr[1]] = cty.ObjectVal(src)
ctx.Variables[dataBlock] = cty.ObjectVal(data)
case localRef:
ctx.Variables[RefData] = cty.ObjectVal(data)
case RefLocal:
locals := make(map[string]cty.Value)
if vv, ok := ctx.Variables[localRef]; ok {
if vv, ok := ctx.Variables[RefLocal]; ok {
locals = vv.AsValueMap()
}
locals[n.addr[1]] = v
ctx.Variables[localRef] = cty.ObjectVal(locals)
ctx.Variables[RefLocal] = cty.ObjectVal(locals)
default:
ctx.Variables[n.addr[0]] = v
}
@ -212,7 +212,25 @@ func (s *State) evalReferences(ctx *hcl.EvalContext, body *hclsyntax.Body) error
return err
}
}
dataref := dataRefs(body)
for _, n := range nodes {
// Evaluate data sources only if they were referenced by other top-level
// blocks/attributes or if they reference other evaluated data sources.
if n.addr[0] == BlockData {
exists := func() bool {
for _, r := range dataref {
t, ok1 := r[1].(hcl.TraverseAttr)
l, ok2 := r[2].(hcl.TraverseAttr)
if ok1 && ok2 && t.Name == n.addr[1] && l.Name == n.addr[2] {
return true
}
}
return false
}()
if !exists {
continue
}
}
if err := visit(n); err != nil {
return err
}
@ -221,15 +239,15 @@ func (s *State) evalReferences(ctx *hcl.EvalContext, body *hclsyntax.Body) error
return nil
}
func mergeCtxVar(ctx *hcl.EvalContext, vals map[string]cty.Value) {
v, ok := ctx.Variables[varRef]
func mergeCtxVar(ctx *hcl.EvalContext, values map[string]cty.Value) {
v, ok := ctx.Variables[RefVar]
if ok {
v.ForEachElement(func(key cty.Value, val cty.Value) (stop bool) {
vals[key.AsString()] = val
values[key.AsString()] = val
return false
})
}
ctx.Variables[varRef] = cty.ObjectVal(vals)
ctx.Variables[RefVar] = cty.ObjectVal(values)
}
func setBlockVars(ctx *hcl.EvalContext, b *hclsyntax.Body) (*hcl.EvalContext, error) {
@ -273,6 +291,10 @@ func blockVars(blocks hclsyntax.Blocks, parentAddr string, defs *blockDef) (map[
}
self := addr(parentAddr, name, blkName, qualifier)
attrs["__ref"] = cty.StringVal(self)
// Skip naming blocks with "name" attribute.
if _, ok := blk.Body.Attributes["name"]; !ok {
attrs["name"] = cty.StringVal(blkName)
}
varMap, err := blockVars(blk.Body.Blocks, self, def)
if err != nil {
return nil, err
@ -374,15 +396,23 @@ var (
// Built-in blocks.
const (
varBlock = "variable"
dataBlock = "data"
localsBlock = "locals"
forEachAttr = "for_each"
eachRef = "each"
varRef = "var"
localRef = "local"
BlockData = "data"
BlockLocals = "locals"
BlockVariable = "variable"
RefData = "data"
RefVar = "var"
RefLocal = "local"
AttrName = "name"
forEachAttr = "for_each"
eachRef = "each"
)
// Variables represents the dynamic variables used in a body.
type Variables struct {
Var, Local map[string]bool
Data map[string]map[string]bool
}
// defRegistry returns a tree of blockDef structs representing the schema of the
// blocks in the *hclsyntax.Body. The returned fields and children of each type
// are an intersection of all existing blocks of the same type.
@ -393,7 +423,7 @@ func defRegistry(b *hclsyntax.Body) *blockDef {
}
for _, blk := range b.Blocks {
// variable definition blocks are available in the HCL source but not reachable by reference.
if blk.Type == varBlock {
if blk.Type == BlockVariable {
continue
}
reg.child(extractDef(blk, reg))
@ -430,6 +460,7 @@ func (t *blockDef) asCty() cty.Type {
for attr := range t.fields {
f[attr] = ctyNilType
}
f["name"] = cty.String
f["__ref"] = cty.String
for _, c := range t.children {
f[c.name] = c.asCty()
@ -454,11 +485,28 @@ func extractDef(blk *hclsyntax.Block, parent *blockDef) *blockDef {
}
func bodyVars(b *hclsyntax.Body) (vars []hcl.Traversal) {
for _, attr := range b.Attributes {
vars = append(vars, hclsyntax.Variables(attr.Expr)...)
for _, a := range b.Attributes {
vars = append(vars, hclsyntax.Variables(a.Expr)...)
}
for _, b := range b.Blocks {
vars = append(vars, bodyVars(b.Body)...)
}
return
}
// dataRefs returns all data source referenced in the body.
func dataRefs(b *hclsyntax.Body) (refs []hcl.Traversal) {
for _, a := range b.Attributes {
for _, v := range hclsyntax.Variables(a.Expr) {
if v.RootName() == RefData {
refs = append(refs, v)
}
}
}
for _, b := range b.Blocks {
if b.Type != BlockData {
refs = append(refs, dataRefs(b.Body)...)
}
}
return
}

View File

@ -496,7 +496,7 @@ func scanPtr(key string, r *Resource, field reflect.Value) error {
default:
t, err := gocty.ImpliedType(e)
if err != nil {
return fmt.Errorf("schemahcl: cannot infer type for field %q when scaning pointer: %w", key, err)
return fmt.Errorf("schemahcl: cannot infer type for field %q when scanning pointer: %w", key, err)
}
attr.V, err = gocty.ToCtyValue(e, t)
if err != nil {

View File

@ -1,261 +0,0 @@
// Copyright 2021-present The Atlas Authors. All rights reserved.
// This source code is licensed under the Apache 2.0 license found
// in the LICENSE file in the root directory of this source tree.
package schemahcl
import (
"errors"
"fmt"
"reflect"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function"
)
type (
// Config configures an unmarshaling.
Config struct {
types []*TypeSpec
newCtx func() *hcl.EvalContext
pathVars map[string]map[string]cty.Value
pathFuncs map[string]map[string]function.Function
datasrc, initblk map[string]func(*hcl.EvalContext, *hclsyntax.Block) (cty.Value, error)
}
// Option configures a Config.
Option func(*Config)
)
// New returns a State configured with options.
func New(opts ...Option) *State {
cfg := &Config{
pathVars: make(map[string]map[string]cty.Value),
pathFuncs: make(map[string]map[string]function.Function),
newCtx: func() *hcl.EvalContext {
return stdTypes(&hcl.EvalContext{
Functions: stdFuncs(),
Variables: make(map[string]cty.Value),
})
},
}
for _, opt := range opts {
opt(cfg)
}
return &State{config: cfg}
}
// WithScopedEnums configured a list of allowed ENUMs to be used in
// the given context, block or attribute. For example, the following
// option allows setting HASH or BTREE to the "using" attribute in
// "index" block.
//
// WithScopedEnums("table.index.type", "HASH", "BTREE")
//
// table "t" {
// ...
// index "i" {
// type = HASH // Allowed.
// type = INVALID // Not Allowed.
// }
// }
func WithScopedEnums(path string, enums ...string) Option {
return func(c *Config) {
vars := make(map[string]cty.Value, len(enums))
for i := range enums {
vars[enums[i]] = cty.StringVal(enums[i])
}
c.pathVars[path] = vars
}
}
// WithVariables registers a list of variables to be injected into the context.
func WithVariables(vars map[string]cty.Value) Option {
return func(c *Config) {
c.newCtx = func() *hcl.EvalContext {
return stdTypes(&hcl.EvalContext{
Functions: stdFuncs(),
Variables: vars,
})
}
}
}
// WithDataSource registers a data source name and its corresponding handler.
// e.g., the example below registers a data source named "text" that returns
// the string defined in the data source block.
//
// WithDataSource("text", func(ctx *hcl.EvalContext, b *hclsyntax.Block) (cty.Value, hcl.Diagnostics) {
// attrs, diags := b.Body.JustAttributes()
// if diags.HasErrors() {
// return cty.NilVal, diags
// }
// v, diags := attrs["value"].Expr.Value(ctx)
// if diags.HasErrors() {
// return cty.NilVal, diags
// }
// return cty.ObjectVal(map[string]cty.Value{"output": v}), nil
// })
//
// data "text" "hello" {
// value = "hello world"
// }
func WithDataSource(name string, h func(*hcl.EvalContext, *hclsyntax.Block) (cty.Value, error)) Option {
return func(c *Config) {
if c.datasrc == nil {
c.datasrc = make(map[string]func(*hcl.EvalContext, *hclsyntax.Block) (cty.Value, error))
}
c.datasrc[name] = h
}
}
// WithInitBlock registers a block that evaluates (first) to a cty.Value,
// has no labels, and can be defined only once. For example:
//
// WithInitBlock("atlas", func(ctx *hcl.EvalContext, b *hclsyntax.Block) (cty.Value, hcl.Diagnostics) {
// attrs, diags := b.Body.JustAttributes()
// if diags.HasErrors() {
// return cty.NilVal, diags
// }
// v, diags := attrs["modules"].Expr.Value(ctx)
// if diags.HasErrors() {
// return cty.NilVal, diags
// }
// return cty.ObjectVal(map[string]cty.Value{"modules": v}), nil
// })
func WithInitBlock(name string, h func(*hcl.EvalContext, *hclsyntax.Block) (cty.Value, error)) Option {
return func(c *Config) {
if c.initblk == nil {
c.initblk = make(map[string]func(*hcl.EvalContext, *hclsyntax.Block) (cty.Value, error))
}
c.initblk[name] = h
}
}
// WithTypes configures the given types as identifiers in the unmarshal
// context. The path controls where the usage of this type is allowed.
func WithTypes(path string, typeSpecs []*TypeSpec) Option {
vars := make(map[string]cty.Value)
funcs := make(map[string]function.Function)
for _, ts := range typeSpecs {
typeSpec := ts
// If no required args exist, register the type as a variable in the HCL context.
if len(typeFuncReqArgs(typeSpec)) == 0 {
typ := &Type{T: typeSpec.T}
vars[typeSpec.Name] = cty.CapsuleVal(ctyTypeSpec, typ)
}
// If func args exist, register the type as a function in HCL.
if len(typeFuncArgs(typeSpec)) > 0 {
funcs[typeSpec.Name] = typeFuncSpec(typeSpec)
}
}
return func(c *Config) {
c.types = append(c.types, typeSpecs...)
c.pathVars[path] = vars
c.pathFuncs[path] = funcs
}
}
func rawExprImpl() function.Function {
return function.New(&function.Spec{
Params: []function.Parameter{
{Name: "def", Type: cty.String, AllowNull: false},
},
Type: function.StaticReturnType(ctyRawExpr),
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
x := args[0].AsString()
if len(x) == 0 {
return cty.NilVal, errors.New("empty expression")
}
t := &RawExpr{X: x}
return cty.CapsuleVal(ctyRawExpr, t), nil
},
})
}
// typeFuncSpec returns the HCL function for defining the type in the spec.
func typeFuncSpec(typeSpec *TypeSpec) function.Function {
spec := &function.Spec{
Type: function.StaticReturnType(ctyTypeSpec),
}
for _, arg := range typeFuncArgs(typeSpec) {
if arg.Kind == reflect.Slice || !arg.Required {
spec.VarParam = &function.Parameter{
Name: "args",
Type: cty.DynamicPseudoType,
}
continue
}
p := function.Parameter{
Name: arg.Name,
AllowNull: !arg.Required,
}
switch arg.Kind {
case reflect.String:
p.Type = cty.String
case reflect.Int, reflect.Float32, reflect.Int64:
p.Type = cty.Number
case reflect.Bool:
p.Type = cty.Bool
}
spec.Params = append(spec.Params, p)
}
spec.Impl = typeFuncSpecImpl(spec, typeSpec)
return function.New(spec)
}
// typeFuncSpecImpl returns the function implementation for the HCL function spec.
func typeFuncSpecImpl(_ *function.Spec, typeSpec *TypeSpec) function.ImplFunc {
return func(args []cty.Value, retType cty.Type) (cty.Value, error) {
t := &Type{
T: typeSpec.T,
}
if len(args) > len(typeSpec.Attributes) && typeSpec.Attributes[len(typeSpec.Attributes)-1].Kind != reflect.Slice {
return cty.NilVal, fmt.Errorf("too many arguments for type definition %q", typeSpec.Name)
}
// TypeRegistry enforces that:
// 1. Required attrs come before optionals
// 2. Slice attrs can only be last
for _, attr := range typeFuncArgs(typeSpec) {
// If the attribute is a slice, read all remaining args into a list value.
if attr.Kind == reflect.Slice {
t.Attrs = append(t.Attrs, &Attr{K: attr.Name, V: cty.ListVal(args)})
break
}
if len(args) == 0 {
break
}
t.Attrs = append(t.Attrs, &Attr{K: attr.Name, V: args[0]})
args = args[1:]
}
return cty.CapsuleVal(ctyTypeSpec, t), nil
}
}
// typeFuncArgs returns the type attributes that are configured via arguments to the
// type definition, for example precision and scale in a decimal definition, i.e `decimal(10,2)`.
func typeFuncArgs(spec *TypeSpec) []*TypeAttr {
var args []*TypeAttr
for _, attr := range spec.Attributes {
// TODO(rotemtam): this should be defined on the TypeSpec.
if attr.Name == "unsigned" {
continue
}
args = append(args, attr)
}
return args
}
// typeFuncReqArgs returns the required type attributes that are configured via arguments.
// for instance, in MySQL a field may be defined as both `int` and `int(10)`, in this case
// it is not a required parameter.
func typeFuncReqArgs(spec *TypeSpec) []*TypeAttr {
var args []*TypeAttr
for _, arg := range typeFuncArgs(spec) {
if arg.Required {
args = append(args, arg)
}
}
return args
}

View File

@ -6,6 +6,7 @@ package schemahcl
import (
"bytes"
"errors"
"fmt"
"reflect"
"sort"
@ -20,6 +21,198 @@ import (
"github.com/zclconf/go-cty/cty/function"
)
type (
// Config configures an unmarshaling.
Config struct {
types []*TypeSpec
vars map[string]cty.Value
funcs map[string]function.Function
pathVars map[string]map[string]cty.Value
pathFuncs map[string]map[string]function.Function
datasrc, initblk map[string]func(*hcl.EvalContext, *hclsyntax.Block) (cty.Value, error)
validator func() SchemaValidator
}
// Option configures a Config.
Option func(*Config)
)
// New returns a State configured with options.
func New(opts ...Option) *State {
cfg := &Config{
vars: make(map[string]cty.Value),
funcs: make(map[string]function.Function),
pathVars: make(map[string]map[string]cty.Value),
pathFuncs: make(map[string]map[string]function.Function),
}
for _, opt := range opts {
opt(cfg)
}
for n, f := range stdFuncs() {
cfg.funcs[n] = f
}
return &State{
config: cfg,
newCtx: func() *hcl.EvalContext {
return stdTypes(&hcl.EvalContext{
Variables: cfg.vars,
Functions: cfg.funcs,
})
},
}
}
// WithScopedEnums configured a list of allowed ENUMs to be used in
// the given context, block or attribute. For example, the following
// option allows setting HASH or BTREE to the "using" attribute in
// "index" block.
//
// WithScopedEnums("table.index.type", "HASH", "BTREE")
//
// table "t" {
// ...
// index "i" {
// type = HASH // Allowed.
// type = INVALID // Not Allowed.
// }
// }
func WithScopedEnums(path string, enums ...string) Option {
return func(c *Config) {
vars := make(map[string]cty.Value, len(enums))
for i := range enums {
vars[enums[i]] = cty.StringVal(enums[i])
}
c.pathVars[path] = vars
}
}
// WithVariables registers a list of variables to be injected into the context.
func WithVariables(vars map[string]cty.Value) Option {
return func(c *Config) {
if c.vars == nil {
c.vars = make(map[string]cty.Value)
}
for n, v := range vars {
c.vars[n] = v
}
}
}
// WithFunctions registers a list of functions to be injected into the context.
func WithFunctions(funcs map[string]function.Function) Option {
return func(c *Config) {
if c.funcs == nil {
c.funcs = make(map[string]function.Function)
}
for n, f := range funcs {
c.funcs[n] = f
}
}
}
// WithDataSource registers a data source name and its corresponding handler.
// e.g., the example below registers a data source named "text" that returns
// the string defined in the data source block.
//
// WithDataSource("text", func(ctx *hcl.EvalContext, b *hclsyntax.Block) (cty.Value, hcl.Diagnostics) {
// attrs, diags := b.Body.JustAttributes()
// if diags.HasErrors() {
// return cty.NilVal, diags
// }
// v, diags := attrs["value"].Expr.Value(ctx)
// if diags.HasErrors() {
// return cty.NilVal, diags
// }
// return cty.ObjectVal(map[string]cty.Value{"output": v}), nil
// })
//
// data "text" "hello" {
// value = "hello world"
// }
func WithDataSource(name string, h func(*hcl.EvalContext, *hclsyntax.Block) (cty.Value, error)) Option {
return func(c *Config) {
if c.datasrc == nil {
c.datasrc = make(map[string]func(*hcl.EvalContext, *hclsyntax.Block) (cty.Value, error))
}
c.datasrc[name] = h
}
}
// WithInitBlock registers a block that evaluates (first) to a cty.Value,
// has no labels, and can be defined only once. For example:
//
// WithInitBlock("atlas", func(ctx *hcl.EvalContext, b *hclsyntax.Block) (cty.Value, hcl.Diagnostics) {
// attrs, diags := b.Body.JustAttributes()
// if diags.HasErrors() {
// return cty.NilVal, diags
// }
// v, diags := attrs["modules"].Expr.Value(ctx)
// if diags.HasErrors() {
// return cty.NilVal, diags
// }
// return cty.ObjectVal(map[string]cty.Value{"modules": v}), nil
// })
func WithInitBlock(name string, h func(*hcl.EvalContext, *hclsyntax.Block) (cty.Value, error)) Option {
return func(c *Config) {
if c.initblk == nil {
c.initblk = make(map[string]func(*hcl.EvalContext, *hclsyntax.Block) (cty.Value, error))
}
c.initblk[name] = h
}
}
// WithTypes configures the given types as identifiers in the unmarshal
// context. The path controls where the usage of this type is allowed.
func WithTypes(path string, typeSpecs []*TypeSpec) Option {
vars := make(map[string]cty.Value)
funcs := make(map[string]function.Function)
for _, ts := range typeSpecs {
typeSpec := ts
// If no required args exist, register the type as a variable in the HCL context.
if len(typeFuncReqArgs(typeSpec)) == 0 {
typ := &Type{T: typeSpec.T}
vars[typeSpec.Name] = cty.CapsuleVal(ctyTypeSpec, typ)
}
// If func args exist, register the type as a function in HCL.
if len(typeFuncArgs(typeSpec)) > 0 {
funcs[typeSpec.Name] = typeFuncSpec(typeSpec)
}
}
return func(c *Config) {
c.types = append(c.types, typeSpecs...)
c.pathVars[path] = vars
c.pathFuncs[path] = funcs
}
}
type (
// SchemaValidator is the interface used for validating HCL documents.
SchemaValidator interface {
Err() error
ValidateBody(*hcl.EvalContext, *hclsyntax.Body) (func() error, error)
ValidateBlock(*hcl.EvalContext, *hclsyntax.Block) (func() error, error)
ValidateAttribute(*hcl.EvalContext, *hclsyntax.Attribute, cty.Value) error
}
nopValidator struct{}
)
func (nopValidator) Err() error { return nil }
func (nopValidator) ValidateBody(*hcl.EvalContext, *hclsyntax.Body) (func() error, error) {
return func() error { return nil }, nil
}
func (nopValidator) ValidateBlock(*hcl.EvalContext, *hclsyntax.Block) (func() error, error) {
return func() error { return nil }, nil
}
func (nopValidator) ValidateAttribute(*hcl.EvalContext, *hclsyntax.Attribute, cty.Value) error {
return nil
}
// WithSchemaValidator registers a schema validator to be used during unmarshaling.
func WithSchemaValidator(v func() SchemaValidator) Option {
return func(c *Config) {
c.validator = v
}
}
// Marshal returns the Atlas HCL encoding of v.
var Marshal = MarshalerFunc(New().MarshalSpec)
@ -27,6 +220,7 @@ type (
// State is used to evaluate and marshal Atlas HCL documents and stores a configuration for these operations.
State struct {
config *Config
newCtx func() *hcl.EvalContext
}
// Evaluator is the interface that wraps the Eval function.
Evaluator interface {
@ -69,7 +263,7 @@ func (s *State) EvalFiles(paths []string, v any, input map[string]cty.Value) err
// Eval evaluates the parsed HCL documents using the input variables and populates v
// using the result.
func (s *State) Eval(parsed *hclparse.Parser, v any, input map[string]cty.Value) error {
ctx := s.config.newCtx()
ctx := s.newCtx()
reg := &blockDef{
fields: make(map[string]struct{}),
children: make(map[string]*blockDef),
@ -90,7 +284,7 @@ func (s *State) Eval(parsed *hclparse.Parser, v any, input map[string]cty.Value)
for _, b := range body.Blocks {
switch {
// Variable blocks are not reachable by reference.
case b.Type == varBlock:
case b.Type == BlockVariable:
continue
// Semi-evaluate blocks with the for_each meta argument.
case b.Body != nil && b.Body.Attributes[forEachAttr] != nil:
@ -121,15 +315,23 @@ func (s *State) Eval(parsed *hclparse.Parser, v any, input map[string]cty.Value)
sort.Slice(fileNames, func(i, j int) bool {
return fileNames[i] < fileNames[j]
})
for _, fn := range fileNames {
file := files[fn]
r, err := s.resource(ctx, file)
vr := SchemaValidator(&nopValidator{})
if s.config.validator != nil {
vr = s.config.validator()
}
for _, name := range fileNames {
file := files[name]
r, err := s.resource(ctx, vr, file)
if err != nil {
return err
}
spec.Children = append(spec.Children, r.Children...)
spec.Attrs = append(spec.Attrs, r.Attrs...)
}
// Validators can fail fast or accumulate errors.
if err := vr.Err(); err != nil {
return err
}
if err := patchRefs(spec); err != nil {
return err
}
@ -208,12 +410,16 @@ func (r addrRef) load(res *Resource, track string) addrRef {
}
// resource converts the hcl file to a schemahcl.Resource.
func (s *State) resource(ctx *hcl.EvalContext, file *hcl.File) (*Resource, error) {
func (s *State) resource(ctx *hcl.EvalContext, vr SchemaValidator, file *hcl.File) (*Resource, error) {
body, ok := file.Body.(*hclsyntax.Body)
if !ok {
return nil, fmt.Errorf("schemahcl: expected remainder to be of type *hclsyntax.Body")
}
attrs, err := s.toAttrs(ctx, body.Attributes, nil)
closeScope, err := vr.ValidateBody(ctx, body)
if err != nil {
return nil, err
}
attrs, err := s.toAttrs(ctx, vr, body.Attributes, nil)
if err != nil {
return nil, err
}
@ -222,19 +428,22 @@ func (s *State) resource(ctx *hcl.EvalContext, file *hcl.File) (*Resource, error
}
for _, blk := range body.Blocks {
// variable blocks may be included in the document but are skipped in unmarshaling.
if blk.Type == varBlock {
if blk.Type == BlockVariable {
continue
}
ctx, err := setBlockVars(ctx.NewChild(), blk.Body)
if err != nil {
return nil, err
}
resource, err := s.toResource(ctx, blk, []string{blk.Type})
resource, err := s.toResource(ctx, vr, blk, []string{blk.Type})
if err != nil {
return nil, err
}
res.Children = append(res.Children, resource)
}
if err := closeScope(); err != nil {
return nil, err
}
return res, nil
}
@ -270,25 +479,38 @@ func (s *State) mayScopeContext(ctx *hcl.EvalContext, scope []string) *hcl.EvalC
return nctx
}
func (s *State) toAttrs(ctx *hcl.EvalContext, hclAttrs hclsyntax.Attributes, scope []string) ([]*Attr, error) {
func (s *State) toAttrs(ctx *hcl.EvalContext, vr SchemaValidator, hclAttrs hclsyntax.Attributes, scope []string) ([]*Attr, error) {
var attrs []*Attr
for _, hclAttr := range hclAttrs {
scope := append(scope, hclAttr.Name)
value, diag := hclAttr.Expr.Value(s.mayScopeContext(ctx, scope))
var (
scope = append(scope, hclAttr.Name)
nctx = s.mayScopeContext(ctx, scope)
)
value, diag := hclAttr.Expr.Value(nctx)
if diag.HasErrors() {
return nil, s.typeError(diag, scope)
}
if err := vr.ValidateAttribute(ctx, hclAttr, value); err != nil {
return nil, err
}
at := &Attr{K: hclAttr.Name}
switch t := value.Type(); {
case isRef(value):
at.V = cty.CapsuleVal(ctyRefType, &Ref{V: value.GetAttr("__ref").AsString()})
case (t.IsTupleType() || t.IsListType() || t.IsSetType()) && value.LengthInt() > 0:
values := make([]cty.Value, 0, value.LengthInt())
var (
vt cty.Type
values = make([]cty.Value, 0, value.LengthInt())
)
for it := value.ElementIterator(); it.Next(); {
_, v := it.Element()
if isRef(v) {
v = cty.CapsuleVal(ctyRefType, &Ref{V: v.GetAttr("__ref").AsString()})
}
if vt != cty.NilType && vt != v.Type() {
return nil, fmt.Errorf("%s: mixed list types used in %q attribute", hclAttr.SrcRange, hclAttr.Name)
}
vt = v.Type()
values = append(values, v)
}
at.V = cty.ListVal(values)
@ -331,16 +553,16 @@ func (s *State) typeError(diag hcl.Diagnostics, scope []string) error {
return diag
}
// isRef checks if the given value is a reference or a list of references.
// Exists here for backward compatibility, use isOneRef and isRefList instead.
func isRef(v cty.Value) bool {
t := v.Type()
if !t.IsObjectType() {
if !v.Type().IsObjectType() {
return false
}
if t.HasAttribute("__ref") {
if isOneRef(v) {
return true
}
it := v.ElementIterator()
for it.Next() {
for it := v.ElementIterator(); it.Next(); {
if _, v := it.Element(