package plugin import ( "errors" "fmt" "github.com/hashicorp/hcl/v2/hclwrite" "github.com/zclconf/go-cty/cty" rpcv1 "code.icb4dc0.de/buildr/api/generated/common/v1" "code.icb4dc0.de/buildr/buildr/internal/hcl" ) func (m Module) MarshalHCL(block *hclwrite.Block) error { for s, value := range m.modSpec.Values { switch value.Kind { case rpcv1.ModuleSpec_ValueKindUnknown, rpcv1.ModuleSpec_ValueKindAttribute: if mapped, err := mapSpecValueToCty(value); err != nil { return err } else { block.Body().SetAttributeValue(s, mapped) } case rpcv1.ModuleSpec_ValueKindBlock: case rpcv1.ModuleSpec_ValueKindLabel: if value.Type != rpcv1.ModuleSpec_ValueTypeSingle { return errors.New("only single values are supported as labels") } if value.SingleValue == nil { return errors.New("single value is nil") } if s, ok := value.SingleValue.(*rpcv1.ModuleSpec_Value_StringValue); !ok { return errors.New("single value is not a string - only strings are supported as labels") } else { block.SetLabels(append(block.Labels(), s.StringValue)) } } } return nil } //nolint:gocyclo // cannot be less complex func mapSpecValueToCty(value *rpcv1.ModuleSpec_Value) (cty.Value, error) { switch value.Type { case rpcv1.ModuleSpec_ValueTypeUnknown: return cty.Value{}, errors.New("cannot map unknown value type") case rpcv1.ModuleSpec_ValueTypeSingle: switch v := value.SingleValue.(type) { case *rpcv1.ModuleSpec_Value_BoolValue: return cty.BoolVal(v.BoolValue), nil case *rpcv1.ModuleSpec_Value_StringValue: return cty.StringVal(v.StringValue), nil case *rpcv1.ModuleSpec_Value_IntValue: return cty.NumberIntVal(v.IntValue), nil case *rpcv1.ModuleSpec_Value_DoubleValue: return cty.NumberFloatVal(v.DoubleValue), nil default: return cty.NilVal, fmt.Errorf("unsupported value type %q", value.Type) } case rpcv1.ModuleSpec_ValueTypeStringSlice: return hcl.MapToCtyVal(value.StringValues, hcl.MappingCfg{}) case rpcv1.ModuleSpec_ValueTypeIntSlice: return hcl.MapToCtyVal(value.IntValues, hcl.MappingCfg{}) case rpcv1.ModuleSpec_ValueTypeDoubleSlice: return hcl.MapToCtyVal(value.DoubleValues, hcl.MappingCfg{}) case rpcv1.ModuleSpec_ValueTypeBoolSlice: return hcl.MapToCtyVal(value.BoolValues, hcl.MappingCfg{}) case rpcv1.ModuleSpec_ValueTypeObject: return cty.Value{}, errors.New("object type are right now not supported (yet)") case rpcv1.ModuleSpec_ValueTypeMap: if len(value.ComplexValue) == 0 { return cty.MapValEmpty(cty.String), nil } mappedVal := make(map[string]cty.Value, len(value.ComplexValue)) for k, v := range value.ComplexValue { if mapped, err := mapSpecValueToCty(v); err != nil { return cty.Value{}, err } else { mappedVal[k] = mapped } } return cty.MapVal(mappedVal), nil default: return cty.NilVal, fmt.Errorf("unsupported value type %q", value.Type) } }