Add BlockAttrs

This commit is contained in:
Alex Dadgar 2018-10-15 20:47:38 -07:00
parent 06719d0b5a
commit 3e7008c2dc
5 changed files with 324 additions and 75 deletions

View File

@ -56,6 +56,9 @@ func decodeSpecBlock(spec *Spec, impliedName string) (hcldec.Spec, hcl.Diagnosti
case *Spec_BlockValue:
return decodeBlockSpec(spec.GetBlockValue(), impliedName)
case *Spec_BlockAttrs:
return decodeBlockAttrsSpec(spec.GetBlockAttrs(), impliedName)
case *Spec_BlockList:
return decodeBlockListSpec(spec.GetBlockList(), impliedName)
@ -156,6 +159,38 @@ func decodeBlockSpec(block *Block, impliedName string) (hcldec.Spec, hcl.Diagnos
return spec, diags
}
func decodeBlockAttrsSpec(block *BlockAttrs, impliedName string) (hcldec.Spec, hcl.Diagnostics) {
// Convert the string type to an hcl.Expression
typeExpr, diags := hclsyntax.ParseExpression([]byte(block.GetType()), "proto", emptyPos)
if diags.HasErrors() {
return nil, diags
}
spec := &hcldec.BlockAttrsSpec{
TypeName: impliedName,
Required: block.GetRequired(),
}
if n := block.GetName(); n != "" {
spec.TypeName = n
}
var typeDiags hcl.Diagnostics
spec.ElementType, typeDiags = evalTypeExpr(typeExpr)
diags = append(diags, typeDiags...)
if spec.TypeName == "" {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Missing name in block_attrs spec",
Detail: "The name attribute is required, to specify the block attr name that is expected in an input HCL file.",
})
return nil, diags
}
return spec, diags
}
func decodeBlockListSpec(block *BlockList, impliedName string) (hcldec.Spec, hcl.Diagnostics) {
spec := &hcldec.BlockListSpec{
TypeName: impliedName,

View File

@ -281,6 +281,44 @@ func TestDec_Convert_Block(t *testing.T) {
testSpecConversions(t, tests)
}
func TestDec_Convert_BlockAttrs(t *testing.T) {
t.Parallel()
tests := []testConversions{
{
Name: "block attr",
Input: &Spec{
Block: &Spec_BlockAttrs{
BlockAttrs: &BlockAttrs{
Name: "test",
Type: "string",
Required: true,
},
},
},
Expected: &hcldec.BlockAttrsSpec{
TypeName: "test",
ElementType: cty.String,
Required: true,
},
},
{
Name: "block list no name",
Input: &Spec{
Block: &Spec_BlockAttrs{
BlockAttrs: &BlockAttrs{
Type: "string",
Required: true,
},
},
},
ExpectedError: "Missing name in block_attrs spec",
},
}
testSpecConversions(t, tests)
}
func TestDec_Convert_BlockList(t *testing.T) {
t.Parallel()

View File

@ -1,5 +1,5 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: github.com/hashicorp/nomad/plugins/shared/hclspec/hcl_spec.proto
// source: hcl_spec.proto
package hclspec
@ -78,6 +78,7 @@ type Spec struct {
// *Spec_Array
// *Spec_Attr
// *Spec_BlockValue
// *Spec_BlockAttrs
// *Spec_BlockList
// *Spec_BlockSet
// *Spec_BlockMap
@ -93,7 +94,7 @@ func (m *Spec) Reset() { *m = Spec{} }
func (m *Spec) String() string { return proto.CompactTextString(m) }
func (*Spec) ProtoMessage() {}
func (*Spec) Descriptor() ([]byte, []int) {
return fileDescriptor_hcl_spec_2b7d8262531848bd, []int{0}
return fileDescriptor_hcl_spec_b17a3e0d58741859, []int{0}
}
func (m *Spec) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Spec.Unmarshal(m, b)
@ -133,24 +134,28 @@ type Spec_BlockValue struct {
BlockValue *Block `protobuf:"bytes,4,opt,name=block_value,json=blockValue,proto3,oneof"`
}
type Spec_BlockAttrs struct {
BlockAttrs *BlockAttrs `protobuf:"bytes,5,opt,name=block_attrs,json=blockAttrs,proto3,oneof"`
}
type Spec_BlockList struct {
BlockList *BlockList `protobuf:"bytes,5,opt,name=block_list,json=blockList,proto3,oneof"`
BlockList *BlockList `protobuf:"bytes,6,opt,name=block_list,json=blockList,proto3,oneof"`
}
type Spec_BlockSet struct {
BlockSet *BlockSet `protobuf:"bytes,6,opt,name=block_set,json=blockSet,proto3,oneof"`
BlockSet *BlockSet `protobuf:"bytes,7,opt,name=block_set,json=blockSet,proto3,oneof"`
}
type Spec_BlockMap struct {
BlockMap *BlockMap `protobuf:"bytes,7,opt,name=block_map,json=blockMap,proto3,oneof"`
BlockMap *BlockMap `protobuf:"bytes,8,opt,name=block_map,json=blockMap,proto3,oneof"`
}
type Spec_Default struct {
Default *Default `protobuf:"bytes,8,opt,name=default,proto3,oneof"`
Default *Default `protobuf:"bytes,9,opt,name=default,proto3,oneof"`
}
type Spec_Literal struct {
Literal *Literal `protobuf:"bytes,9,opt,name=literal,proto3,oneof"`
Literal *Literal `protobuf:"bytes,10,opt,name=literal,proto3,oneof"`
}
func (*Spec_Object) isSpec_Block() {}
@ -161,6 +166,8 @@ func (*Spec_Attr) isSpec_Block() {}
func (*Spec_BlockValue) isSpec_Block() {}
func (*Spec_BlockAttrs) isSpec_Block() {}
func (*Spec_BlockList) isSpec_Block() {}
func (*Spec_BlockSet) isSpec_Block() {}
@ -206,6 +213,13 @@ func (m *Spec) GetBlockValue() *Block {
return nil
}
func (m *Spec) GetBlockAttrs() *BlockAttrs {
if x, ok := m.GetBlock().(*Spec_BlockAttrs); ok {
return x.BlockAttrs
}
return nil
}
func (m *Spec) GetBlockList() *BlockList {
if x, ok := m.GetBlock().(*Spec_BlockList); ok {
return x.BlockList
@ -248,6 +262,7 @@ func (*Spec) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, f
(*Spec_Array)(nil),
(*Spec_Attr)(nil),
(*Spec_BlockValue)(nil),
(*Spec_BlockAttrs)(nil),
(*Spec_BlockList)(nil),
(*Spec_BlockSet)(nil),
(*Spec_BlockMap)(nil),
@ -280,28 +295,33 @@ func _Spec_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
if err := b.EncodeMessage(x.BlockValue); err != nil {
return err
}
case *Spec_BlockList:
case *Spec_BlockAttrs:
b.EncodeVarint(5<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.BlockAttrs); err != nil {
return err
}
case *Spec_BlockList:
b.EncodeVarint(6<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.BlockList); err != nil {
return err
}
case *Spec_BlockSet:
b.EncodeVarint(6<<3 | proto.WireBytes)
b.EncodeVarint(7<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.BlockSet); err != nil {
return err
}
case *Spec_BlockMap:
b.EncodeVarint(7<<3 | proto.WireBytes)
b.EncodeVarint(8<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.BlockMap); err != nil {
return err
}
case *Spec_Default:
b.EncodeVarint(8<<3 | proto.WireBytes)
b.EncodeVarint(9<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.Default); err != nil {
return err
}
case *Spec_Literal:
b.EncodeVarint(9<<3 | proto.WireBytes)
b.EncodeVarint(10<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.Literal); err != nil {
return err
}
@ -347,7 +367,15 @@ func _Spec_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (
err := b.DecodeMessage(msg)
m.Block = &Spec_BlockValue{msg}
return true, err
case 5: // block.block_list
case 5: // block.block_attrs
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(BlockAttrs)
err := b.DecodeMessage(msg)
m.Block = &Spec_BlockAttrs{msg}
return true, err
case 6: // block.block_list
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
@ -355,7 +383,7 @@ func _Spec_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (
err := b.DecodeMessage(msg)
m.Block = &Spec_BlockList{msg}
return true, err
case 6: // block.block_set
case 7: // block.block_set
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
@ -363,7 +391,7 @@ func _Spec_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (
err := b.DecodeMessage(msg)
m.Block = &Spec_BlockSet{msg}
return true, err
case 7: // block.block_map
case 8: // block.block_map
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
@ -371,7 +399,7 @@ func _Spec_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (
err := b.DecodeMessage(msg)
m.Block = &Spec_BlockMap{msg}
return true, err
case 8: // block.default
case 9: // block.default
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
@ -379,7 +407,7 @@ func _Spec_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (
err := b.DecodeMessage(msg)
m.Block = &Spec_Default{msg}
return true, err
case 9: // block.literal
case 10: // block.literal
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
@ -416,6 +444,11 @@ func _Spec_OneofSizer(msg proto.Message) (n int) {
n += 1 // tag and wire
n += proto.SizeVarint(uint64(s))
n += s
case *Spec_BlockAttrs:
s := proto.Size(x.BlockAttrs)
n += 1 // tag and wire
n += proto.SizeVarint(uint64(s))
n += s
case *Spec_BlockList:
s := proto.Size(x.BlockList)
n += 1 // tag and wire
@ -489,7 +522,7 @@ func (m *Attr) Reset() { *m = Attr{} }
func (m *Attr) String() string { return proto.CompactTextString(m) }
func (*Attr) ProtoMessage() {}
func (*Attr) Descriptor() ([]byte, []int) {
return fileDescriptor_hcl_spec_2b7d8262531848bd, []int{1}
return fileDescriptor_hcl_spec_b17a3e0d58741859, []int{1}
}
func (m *Attr) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Attr.Unmarshal(m, b)
@ -578,7 +611,7 @@ func (m *Block) Reset() { *m = Block{} }
func (m *Block) String() string { return proto.CompactTextString(m) }
func (*Block) ProtoMessage() {}
func (*Block) Descriptor() ([]byte, []int) {
return fileDescriptor_hcl_spec_2b7d8262531848bd, []int{2}
return fileDescriptor_hcl_spec_b17a3e0d58741859, []int{2}
}
func (m *Block) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Block.Unmarshal(m, b)
@ -619,6 +652,92 @@ func (m *Block) GetNested() *Spec {
return nil
}
//
// The BlockAttrs spec type is similar to an Attr spec block of a map type,
// but it produces a map from the attributes of a block rather than from an
// attribute's expression.
//
// ```hcl
// BlockAttrs {
// name = "variables"
// type = string
// required = false
// }
// ```
//
// This allows a map with user-defined keys to be produced within block syntax,
// but due to the constraints of that syntax it also means that the user will
// be unable to dynamically-generate either individual key names using key
// expressions or the entire map value using a `for` expression.
//
// `BlockAttrs` spec blocks accept the following arguments:
//
// `name` (required) - The block type name to expect within the HCL
// input file. This may be omitted when a default name selector is created
// by a parent `object` spec, if the input block type name should match the
// output JSON object property name.
//
// `type` (required) - The value type to require for each of the
// attributes within a matched block. The resulting value will be a JSON
// object whose property values are of this type.
//
// `required` (optional) - If `true`, an error will be produced if a block
// of the given type is not present. If `false` -- the default -- an absent
// block will be indicated by producing `null`.
type BlockAttrs struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"`
Required bool `protobuf:"varint,3,opt,name=required,proto3" json:"required,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *BlockAttrs) Reset() { *m = BlockAttrs{} }
func (m *BlockAttrs) String() string { return proto.CompactTextString(m) }
func (*BlockAttrs) ProtoMessage() {}
func (*BlockAttrs) Descriptor() ([]byte, []int) {
return fileDescriptor_hcl_spec_b17a3e0d58741859, []int{3}
}
func (m *BlockAttrs) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BlockAttrs.Unmarshal(m, b)
}
func (m *BlockAttrs) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_BlockAttrs.Marshal(b, m, deterministic)
}
func (dst *BlockAttrs) XXX_Merge(src proto.Message) {
xxx_messageInfo_BlockAttrs.Merge(dst, src)
}
func (m *BlockAttrs) XXX_Size() int {
return xxx_messageInfo_BlockAttrs.Size(m)
}
func (m *BlockAttrs) XXX_DiscardUnknown() {
xxx_messageInfo_BlockAttrs.DiscardUnknown(m)
}
var xxx_messageInfo_BlockAttrs proto.InternalMessageInfo
func (m *BlockAttrs) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *BlockAttrs) GetType() string {
if m != nil {
return m.Type
}
return ""
}
func (m *BlockAttrs) GetRequired() bool {
if m != nil {
return m.Required
}
return false
}
// BlockList spec type is similar to `Block`, but it accepts zero or
// more blocks of a specified type rather than requiring zero or one. The
// result is a JSON array with one entry per block of the given type.
@ -673,7 +792,7 @@ func (m *BlockList) Reset() { *m = BlockList{} }
func (m *BlockList) String() string { return proto.CompactTextString(m) }
func (*BlockList) ProtoMessage() {}
func (*BlockList) Descriptor() ([]byte, []int) {
return fileDescriptor_hcl_spec_2b7d8262531848bd, []int{3}
return fileDescriptor_hcl_spec_b17a3e0d58741859, []int{4}
}
func (m *BlockList) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BlockList.Unmarshal(m, b)
@ -756,7 +875,7 @@ func (m *BlockSet) Reset() { *m = BlockSet{} }
func (m *BlockSet) String() string { return proto.CompactTextString(m) }
func (*BlockSet) ProtoMessage() {}
func (*BlockSet) Descriptor() ([]byte, []int) {
return fileDescriptor_hcl_spec_2b7d8262531848bd, []int{4}
return fileDescriptor_hcl_spec_b17a3e0d58741859, []int{5}
}
func (m *BlockSet) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BlockSet.Unmarshal(m, b)
@ -855,7 +974,7 @@ func (m *BlockMap) Reset() { *m = BlockMap{} }
func (m *BlockMap) String() string { return proto.CompactTextString(m) }
func (*BlockMap) ProtoMessage() {}
func (*BlockMap) Descriptor() ([]byte, []int) {
return fileDescriptor_hcl_spec_2b7d8262531848bd, []int{5}
return fileDescriptor_hcl_spec_b17a3e0d58741859, []int{6}
}
func (m *BlockMap) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BlockMap.Unmarshal(m, b)
@ -925,7 +1044,7 @@ func (m *Literal) Reset() { *m = Literal{} }
func (m *Literal) String() string { return proto.CompactTextString(m) }
func (*Literal) ProtoMessage() {}
func (*Literal) Descriptor() ([]byte, []int) {
return fileDescriptor_hcl_spec_2b7d8262531848bd, []int{6}
return fileDescriptor_hcl_spec_b17a3e0d58741859, []int{7}
}
func (m *Literal) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Literal.Unmarshal(m, b)
@ -989,7 +1108,7 @@ func (m *Default) Reset() { *m = Default{} }
func (m *Default) String() string { return proto.CompactTextString(m) }
func (*Default) ProtoMessage() {}
func (*Default) Descriptor() ([]byte, []int) {
return fileDescriptor_hcl_spec_2b7d8262531848bd, []int{7}
return fileDescriptor_hcl_spec_b17a3e0d58741859, []int{8}
}
func (m *Default) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Default.Unmarshal(m, b)
@ -1063,7 +1182,7 @@ func (m *Object) Reset() { *m = Object{} }
func (m *Object) String() string { return proto.CompactTextString(m) }
func (*Object) ProtoMessage() {}
func (*Object) Descriptor() ([]byte, []int) {
return fileDescriptor_hcl_spec_2b7d8262531848bd, []int{8}
return fileDescriptor_hcl_spec_b17a3e0d58741859, []int{9}
}
func (m *Object) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Object.Unmarshal(m, b)
@ -1119,7 +1238,7 @@ func (m *Array) Reset() { *m = Array{} }
func (m *Array) String() string { return proto.CompactTextString(m) }
func (*Array) ProtoMessage() {}
func (*Array) Descriptor() ([]byte, []int) {
return fileDescriptor_hcl_spec_2b7d8262531848bd, []int{9}
return fileDescriptor_hcl_spec_b17a3e0d58741859, []int{10}
}
func (m *Array) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Array.Unmarshal(m, b)
@ -1150,6 +1269,7 @@ func init() {
proto.RegisterType((*Spec)(nil), "hashicorp.nomad.plugins.shared.hclspec.Spec")
proto.RegisterType((*Attr)(nil), "hashicorp.nomad.plugins.shared.hclspec.Attr")
proto.RegisterType((*Block)(nil), "hashicorp.nomad.plugins.shared.hclspec.Block")
proto.RegisterType((*BlockAttrs)(nil), "hashicorp.nomad.plugins.shared.hclspec.BlockAttrs")
proto.RegisterType((*BlockList)(nil), "hashicorp.nomad.plugins.shared.hclspec.BlockList")
proto.RegisterType((*BlockSet)(nil), "hashicorp.nomad.plugins.shared.hclspec.BlockSet")
proto.RegisterType((*BlockMap)(nil), "hashicorp.nomad.plugins.shared.hclspec.BlockMap")
@ -1160,49 +1280,47 @@ func init() {
proto.RegisterType((*Array)(nil), "hashicorp.nomad.plugins.shared.hclspec.Array")
}
func init() {
proto.RegisterFile("github.com/hashicorp/nomad/plugins/shared/hclspec/hcl_spec.proto", fileDescriptor_hcl_spec_2b7d8262531848bd)
}
func init() { proto.RegisterFile("hcl_spec.proto", fileDescriptor_hcl_spec_b17a3e0d58741859) }
var fileDescriptor_hcl_spec_2b7d8262531848bd = []byte{
// 612 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x95, 0xcb, 0x6e, 0xd4, 0x3c,
0x14, 0x80, 0x27, 0x33, 0xb9, 0x9e, 0x2e, 0xfe, 0x5f, 0x16, 0x42, 0x51, 0x59, 0x50, 0x65, 0x81,
0xba, 0x80, 0x04, 0xca, 0x06, 0xb1, 0x40, 0x74, 0xd4, 0xa2, 0x00, 0xad, 0x8a, 0x5c, 0x89, 0x05,
0x0b, 0x46, 0x4e, 0xc6, 0x74, 0x4c, 0x73, 0xc3, 0x71, 0x50, 0x47, 0x82, 0x07, 0x61, 0x03, 0x6f,
0xc3, 0x1b, 0xf0, 0x3e, 0xc8, 0x97, 0x4c, 0x0b, 0xea, 0x62, 0x32, 0xb0, 0x60, 0x35, 0x3e, 0x3e,
0xfa, 0xbe, 0x39, 0xb1, 0x8f, 0x6d, 0x78, 0x7a, 0xc6, 0xc4, 0xa2, 0xcb, 0xe2, 0xbc, 0x2e, 0x93,
0x05, 0x69, 0x17, 0x2c, 0xaf, 0x79, 0x93, 0x54, 0x75, 0x49, 0xe6, 0x49, 0x53, 0x74, 0x67, 0xac,
0x6a, 0x93, 0x76, 0x41, 0x38, 0x9d, 0x27, 0x8b, 0xbc, 0x68, 0x1b, 0x9a, 0xcb, 0xdf, 0x99, 0x1c,
0xc4, 0x0d, 0xaf, 0x45, 0x8d, 0xee, 0xac, 0xb0, 0x58, 0x61, 0xb1, 0xc1, 0x62, 0x8d, 0xc5, 0x06,
0x8b, 0xbe, 0x3b, 0x60, 0x9f, 0x36, 0x34, 0x47, 0x29, 0xb8, 0x75, 0xf6, 0x9e, 0xe6, 0x22, 0xb4,
0x76, 0xac, 0xdd, 0xad, 0xbd, 0x38, 0x5e, 0xcf, 0x10, 0x9f, 0x28, 0x2a, 0x1d, 0x61, 0xc3, 0xa3,
0x43, 0x70, 0x08, 0xe7, 0x64, 0x19, 0x8e, 0x95, 0xe8, 0xde, 0xba, 0xa2, 0x7d, 0x09, 0xa5, 0x23,
0xac, 0x69, 0x34, 0x05, 0x7b, 0x5f, 0x08, 0x1e, 0x4e, 0x94, 0xe5, 0xee, 0xda, 0x16, 0x21, 0x78,
0x3a, 0xc2, 0x8a, 0x45, 0xaf, 0x60, 0x2b, 0x2b, 0xea, 0xfc, 0x7c, 0xf6, 0x91, 0x14, 0x1d, 0x0d,
0xed, 0x61, 0x05, 0x4d, 0x25, 0x9a, 0x8e, 0x30, 0x28, 0xc7, 0x6b, 0xa9, 0x40, 0x18, 0x74, 0x34,
0x2b, 0x58, 0x2b, 0x42, 0x47, 0x09, 0x1f, 0x0c, 0x12, 0x1e, 0xb1, 0x56, 0xae, 0x56, 0x90, 0xf5,
0x01, 0x3a, 0x01, 0x1d, 0xcc, 0x5a, 0x2a, 0x42, 0x57, 0x29, 0xef, 0x0f, 0x52, 0x9e, 0x52, 0x69,
0xf4, 0x33, 0x33, 0xbe, 0x14, 0x96, 0xa4, 0x09, 0xbd, 0x0d, 0x84, 0xc7, 0xa4, 0x59, 0x09, 0x8f,
0x49, 0x83, 0x5e, 0x82, 0x37, 0xa7, 0xef, 0x48, 0x57, 0x88, 0xd0, 0x57, 0xba, 0x64, 0x5d, 0xdd,
0x81, 0xc6, 0xd2, 0x11, 0xee, 0x0d, 0x52, 0x56, 0x30, 0x41, 0x39, 0x29, 0xc2, 0x60, 0x98, 0xec,
0x48, 0x63, 0x52, 0x66, 0x0c, 0x53, 0x0f, 0x1c, 0x55, 0x65, 0xf4, 0x42, 0xb7, 0x0b, 0x42, 0x60,
0x57, 0xa4, 0xa4, 0xaa, 0x8b, 0x03, 0xac, 0xc6, 0x72, 0x4e, 0x2c, 0x1b, 0xaa, 0x1a, 0x32, 0xc0,
0x6a, 0x8c, 0xb6, 0xc1, 0xe7, 0xf4, 0x43, 0xc7, 0x38, 0x9d, 0xab, 0x16, 0xf3, 0xf1, 0x2a, 0x8e,
0x3e, 0x83, 0xa3, 0x96, 0xe1, 0x5a, 0xd9, 0x55, 0x70, 0xfc, 0x2b, 0x88, 0x0e, 0xc0, 0xad, 0x68,
0x2b, 0x8c, 0x72, 0x40, 0xd7, 0xca, 0x23, 0x88, 0x0d, 0x1b, 0x7d, 0xb3, 0x20, 0x58, 0xb5, 0xca,
0xb5, 0x35, 0xdc, 0x82, 0xa0, 0x64, 0xd5, 0x8c, 0x09, 0x5a, 0xb6, 0xaa, 0x08, 0x1b, 0xfb, 0x25,
0xab, 0x9e, 0xcb, 0x58, 0x25, 0xc9, 0x85, 0x49, 0x4e, 0x4c, 0x92, 0x5c, 0xe8, 0xe4, 0x65, 0x85,
0xf6, 0x1f, 0x54, 0xf8, 0xd5, 0x02, 0xbf, 0xef, 0xbc, 0x7f, 0xb2, 0xc0, 0x4f, 0xa6, 0x3e, 0xd9,
0xbc, 0xd7, 0xd5, 0x77, 0x13, 0xdc, 0x82, 0x64, 0xb4, 0x90, 0xc5, 0x4d, 0x76, 0x03, 0x6c, 0xa2,
0xbf, 0xb4, 0x81, 0xb7, 0xc1, 0x33, 0xad, 0x8a, 0x6e, 0x80, 0xa3, 0xef, 0x1e, 0xfd, 0xef, 0x3a,
0x88, 0xbe, 0x58, 0xe0, 0x99, 0x93, 0x81, 0x9e, 0x81, 0xd7, 0x70, 0x56, 0x12, 0xbe, 0x34, 0x37,
0xef, 0xb0, 0xff, 0xec, 0x61, 0xe9, 0xe9, 0xcf, 0xe8, 0x78, 0x13, 0x8f, 0x81, 0xa3, 0x1f, 0x16,
0xb8, 0xfa, 0x4e, 0x47, 0x6f, 0x01, 0x88, 0x10, 0x9c, 0x65, 0x9d, 0xa0, 0x6d, 0x68, 0xed, 0x4c,
0x76, 0xb7, 0xf6, 0x9e, 0x0c, 0x7b, 0x17, 0xd4, 0x7d, 0xac, 0x05, 0x87, 0x95, 0xe0, 0x4b, 0x7c,
0xc5, 0xb8, 0x7d, 0x0e, 0xff, 0xfd, 0x96, 0x46, 0xff, 0xc3, 0xe4, 0x9c, 0x2e, 0xcd, 0x6a, 0xc9,
0x21, 0x9a, 0xf6, 0x2b, 0xb8, 0xc9, 0x57, 0x69, 0xf4, 0xf1, 0xf8, 0x91, 0x15, 0x1d, 0x83, 0xa3,
0x5e, 0x18, 0xb9, 0xc7, 0x6a, 0xb6, 0xff, 0xa2, 0x81, 0x7b, 0xac, 0xd9, 0x69, 0xf0, 0xc6, 0x33,
0xf3, 0x99, 0xab, 0x9e, 0xdc, 0x87, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x4f, 0x2c, 0x98, 0x6b,
0xb6, 0x07, 0x00, 0x00,
var fileDescriptor_hcl_spec_b17a3e0d58741859 = []byte{
// 617 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x96, 0xcd, 0x6e, 0xd3, 0x40,
0x10, 0xc7, 0xe3, 0xc4, 0x9f, 0x53, 0x09, 0xd0, 0x0a, 0x21, 0xab, 0x1c, 0xa8, 0x7c, 0x40, 0x3d,
0x80, 0x81, 0x72, 0x41, 0x1c, 0x90, 0x1a, 0xb5, 0xc8, 0x40, 0xa3, 0x56, 0x5b, 0xc1, 0x81, 0x03,
0xd1, 0xda, 0x59, 0x88, 0x89, 0xbf, 0xd8, 0xdd, 0xa0, 0x46, 0x82, 0x07, 0xe1, 0x00, 0x3c, 0x15,
0xef, 0x83, 0xf6, 0xc3, 0x49, 0x41, 0x39, 0xc4, 0xa1, 0x07, 0x6e, 0x3b, 0x3b, 0xf9, 0xff, 0x3c,
0xb3, 0x3b, 0xb3, 0x13, 0xb8, 0x36, 0xcd, 0x8a, 0x31, 0x6f, 0x68, 0x16, 0x37, 0xac, 0x16, 0x35,
0xba, 0x3b, 0x25, 0x7c, 0x9a, 0x67, 0x35, 0x6b, 0xe2, 0xaa, 0x2e, 0xc9, 0x24, 0x6e, 0x8a, 0xf9,
0x87, 0xbc, 0xe2, 0x31, 0x9f, 0x12, 0x46, 0x27, 0xf1, 0x34, 0x2b, 0xe4, 0xaf, 0xa3, 0xef, 0x2e,
0xd8, 0xe7, 0x0d, 0xcd, 0x50, 0x02, 0x6e, 0x9d, 0x7e, 0xa4, 0x99, 0x08, 0xad, 0x3d, 0x6b, 0x7f,
0xe7, 0x20, 0x8e, 0x37, 0x23, 0xc4, 0xa7, 0x4a, 0x95, 0xf4, 0xb0, 0xd1, 0xa3, 0x63, 0x70, 0x08,
0x63, 0x64, 0x11, 0xf6, 0x15, 0xe8, 0xfe, 0xa6, 0xa0, 0x43, 0x29, 0x4a, 0x7a, 0x58, 0xab, 0xd1,
0x10, 0xec, 0x43, 0x21, 0x58, 0x38, 0x50, 0x94, 0x7b, 0x1b, 0x53, 0x84, 0x60, 0x49, 0x0f, 0x2b,
0x2d, 0x3a, 0x83, 0x9d, 0xb4, 0xa8, 0xb3, 0xd9, 0xf8, 0x33, 0x29, 0xe6, 0x34, 0xb4, 0xbb, 0x05,
0x34, 0x94, 0xd2, 0xa4, 0x87, 0x41, 0x31, 0xde, 0x48, 0x04, 0x7a, 0xdd, 0x12, 0x89, 0x10, 0x8c,
0x87, 0x8e, 0x22, 0x1e, 0x74, 0x22, 0xca, 0xc8, 0xf8, 0x12, 0xab, 0x2c, 0x84, 0x41, 0x5b, 0xe3,
0x22, 0xe7, 0x22, 0x74, 0x15, 0xf5, 0x51, 0x27, 0xea, 0x49, 0xce, 0xe5, 0x25, 0x04, 0x69, 0x6b,
0xa0, 0x53, 0xd0, 0xc6, 0x98, 0x53, 0x11, 0x7a, 0x0a, 0xf9, 0xb0, 0x13, 0xf2, 0x9c, 0x4a, 0xa2,
0x9f, 0x9a, 0xf5, 0x0a, 0x58, 0x92, 0x26, 0xf4, 0xb7, 0x00, 0x8e, 0x48, 0xb3, 0x04, 0x8e, 0x48,
0x83, 0x5e, 0x81, 0x37, 0xa1, 0xef, 0xc9, 0xbc, 0x10, 0x61, 0xa0, 0x70, 0x0f, 0x36, 0xc5, 0x1d,
0x69, 0x59, 0xd2, 0xc3, 0x2d, 0x41, 0xc2, 0x8a, 0x5c, 0x50, 0x46, 0x8a, 0x10, 0xba, 0xc1, 0x4e,
0xb4, 0x4c, 0xc2, 0x0c, 0x61, 0xe8, 0x81, 0xa3, 0xa2, 0x8c, 0x5e, 0xea, 0x2a, 0x44, 0x08, 0xec,
0x8a, 0x94, 0x54, 0x35, 0x47, 0x80, 0xd5, 0x5a, 0xee, 0x89, 0x45, 0x43, 0x55, 0x9d, 0x07, 0x58,
0xad, 0xd1, 0x2e, 0xf8, 0x8c, 0x7e, 0x9a, 0xe7, 0x8c, 0x4e, 0x54, 0xe5, 0xfa, 0x78, 0x69, 0x47,
0x5f, 0xc1, 0x51, 0xc7, 0xb0, 0x16, 0x76, 0x59, 0xd8, 0xff, 0x53, 0x88, 0x8e, 0xc0, 0xad, 0x28,
0x17, 0x06, 0xd9, 0xa1, 0x19, 0x64, 0x67, 0x63, 0xa3, 0x8d, 0xce, 0x00, 0x56, 0xf5, 0x77, 0x25,
0x09, 0xfd, 0xb4, 0x20, 0x58, 0x16, 0xdf, 0x5a, 0xe2, 0x6d, 0x08, 0xca, 0xbc, 0x1a, 0xe7, 0x82,
0x96, 0x5c, 0x61, 0x6d, 0xec, 0x97, 0x79, 0xf5, 0x42, 0xda, 0xca, 0x49, 0x2e, 0x8c, 0x73, 0x60,
0x9c, 0xe4, 0x42, 0x3b, 0x57, 0x39, 0xdb, 0xff, 0x90, 0xf3, 0x0f, 0x0b, 0xfc, 0xb6, 0x96, 0xff,
0xcb, 0x00, 0xbf, 0x98, 0xf8, 0x64, 0x3b, 0xac, 0x8b, 0xef, 0x16, 0xb8, 0x05, 0x49, 0x69, 0x21,
0x83, 0x1b, 0xec, 0x07, 0xd8, 0x58, 0x57, 0x54, 0x12, 0x77, 0xc0, 0x33, 0xc5, 0x8f, 0x6e, 0x82,
0xa3, 0x1f, 0x49, 0xfd, 0x75, 0x6d, 0x44, 0xdf, 0x2c, 0xf0, 0x4c, 0xaf, 0xa1, 0xe7, 0xe0, 0x35,
0x2c, 0x2f, 0x09, 0x5b, 0x98, 0x11, 0xd1, 0xed, 0x9b, 0xad, 0x58, 0x72, 0xda, 0xae, 0xef, 0x6f,
0xc3, 0x31, 0xe2, 0xe8, 0x97, 0x05, 0xae, 0x1e, 0x3e, 0xe8, 0x1d, 0x80, 0x7c, 0x8f, 0xf3, 0x74,
0x2e, 0x28, 0x0f, 0xad, 0xbd, 0xc1, 0xfe, 0xce, 0xc1, 0xb3, 0x6e, 0x03, 0x4c, 0x0d, 0x0e, 0x0d,
0x38, 0xae, 0x04, 0x5b, 0xe0, 0x4b, 0xc4, 0xdd, 0x19, 0x5c, 0xff, 0xcb, 0x8d, 0x6e, 0xc0, 0x60,
0x46, 0x17, 0xe6, 0xb4, 0xe4, 0x12, 0x0d, 0xdb, 0x13, 0xdc, 0x26, 0x2b, 0x2d, 0x7d, 0xda, 0x7f,
0x62, 0x45, 0x23, 0x70, 0xd4, 0x28, 0x94, 0x77, 0xac, 0x76, 0xdb, 0x8c, 0x3a, 0xde, 0xb1, 0xd6,
0x0e, 0x83, 0xb7, 0x9e, 0xd9, 0x4f, 0x5d, 0xf5, 0xdf, 0xe0, 0xf1, 0xef, 0x00, 0x00, 0x00, 0xff,
0xff, 0x18, 0x16, 0x39, 0xa4, 0x2d, 0x08, 0x00, 0x00,
}

View File

@ -62,11 +62,12 @@ message Spec {
Array array = 2;
Attr Attr = 3;
Block block_value = 4;
BlockList block_list = 5;
BlockSet block_set = 6;
BlockMap block_map = 7;
Default default = 8;
Literal literal = 9;
BlockAttrs block_attrs = 5;
BlockList block_list = 6;
BlockSet block_set = 7;
BlockMap block_map = 8;
Default default = 9;
Literal literal = 10;
}
}
@ -147,6 +148,45 @@ message Block {
Spec nested = 3;
}
/*
The BlockAttrs spec type is similar to an Attr spec block of a map type,
but it produces a map from the attributes of a block rather than from an
attribute's expression.
```hcl
BlockAttrs {
name = "variables"
type = string
required = false
}
```
This allows a map with user-defined keys to be produced within block syntax,
but due to the constraints of that syntax it also means that the user will
be unable to dynamically-generate either individual key names using key
expressions or the entire map value using a `for` expression.
`BlockAttrs` spec blocks accept the following arguments:
* `name` (required) - The block type name to expect within the HCL
input file. This may be omitted when a default name selector is created
by a parent `object` spec, if the input block type name should match the
output JSON object property name.
* `type` (required) - The value type to require for each of the
attributes within a matched block. The resulting value will be a JSON
object whose property values are of this type.
* `required` (optional) - If `true`, an error will be produced if a block
of the given type is not present. If `false` -- the default -- an absent
block will be indicated by producing `null`.
*/
message BlockAttrs {
string name = 1;
string type = 2;
bool required = 3;
}
/* BlockList spec type is similar to `Block`, but it accepts zero or
more blocks of a specified type rather than requiring zero or one. The
result is a JSON array with one entry per block of the given type.

View File

@ -36,6 +36,15 @@ func BlockSpec(block *Block) *Spec {
}
}
// BlockAttrsSpec wraps the block attrs and returns a spec.
func BlockAttrsSpec(blockAttrs *BlockAttrs) *Spec {
return &Spec{
Block: &Spec_BlockAttrs{
BlockAttrs: blockAttrs,
},
}
}
// BlockListSpec wraps the block list and returns a spec.
func BlockListSpec(blockList *BlockList) *Spec {
return &Spec{
@ -106,6 +115,15 @@ func NewBlock(name string, required bool, nested *Spec) *Spec {
})
}
// NewBlockAttrs returns a new block attrs spec
func NewBlockAttrs(name, elementType string, required bool) *Spec {
return BlockAttrsSpec(&BlockAttrs{
Name: name,
Required: required,
Type: elementType,
})
}
// NewBlockList returns a new block list spec that has no limits.
func NewBlockList(name string, nested *Spec) *Spec {
return NewBlockListLimited(name, 0, 0, nested)