diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ac73e491..70da4a2af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ nav_order: 1 - Removes `receiver_ingesting_remote_write_uri` and `store_uri` Thanos connection info fields - Adds `stringtype` to `flink_external_postgresql_user_config` service integration - Fix `terraform import` for services with additional disk space or read replica service integration +- Run client-side validation for `aiven_kafka_schema` AVRO type schema ## [4.26.0] - 2024-09-25 diff --git a/go.mod b/go.mod index 621b7e39b..4f24e6ae6 100644 --- a/go.mod +++ b/go.mod @@ -10,12 +10,14 @@ require ( github.com/docker/go-units v0.5.0 github.com/google/go-cmp v0.6.0 github.com/gruntwork-io/terratest v0.47.2 + github.com/hamba/avro/v2 v2.26.0 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-framework v1.12.0 github.com/hashicorp/terraform-plugin-go v0.24.0 github.com/hashicorp/terraform-plugin-mux v0.16.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 github.com/kelseyhightower/envconfig v1.4.0 + github.com/rs/zerolog v1.33.0 github.com/samber/lo v1.47.0 github.com/stoewer/go-strcase v1.3.0 github.com/stretchr/testify v1.9.0 @@ -37,7 +39,9 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.7 // indirect - github.com/rs/zerolog v1.33.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect @@ -87,7 +91,7 @@ require ( github.com/hashicorp/yamux v0.1.1 // indirect github.com/jinzhu/copier v0.4.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/klauspost/compress v1.15.11 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect diff --git a/go.sum b/go.sum index 8fe9438fe..96960baa2 100644 --- a/go.sum +++ b/go.sum @@ -199,8 +199,6 @@ github.com/aiven/aiven-go-client/v2 v2.27.0 h1:iTr85xDpD8td3Okj2+djUOfGLlVvngvUw github.com/aiven/aiven-go-client/v2 v2.27.0/go.mod h1:KdHfLIlIRZIfCSEBd39j1Q81jlSb6Nd+oCQKqERfnuA= github.com/aiven/go-api-schemas v1.91.0 h1:jiJpRwFKf3IcuZtMIzDmNyICmX0ayqDYMh9QF0GoFZY= github.com/aiven/go-api-schemas v1.91.0/go.mod h1:qS3E/3R+aKQbHsqXzNHqlXATY1kbVNzhiJvk2IDmADI= -github.com/aiven/go-client-codegen v0.38.0 h1:WnH9CEtVbolqqKr9PlIZZE9pG4lWkNK+H6iyHO/b010= -github.com/aiven/go-client-codegen v0.38.0/go.mod h1:FfbH32Xb+Hx5zeKTIug1Y8SfMeB+AKNRzxgrzkts2oA= github.com/aiven/go-client-codegen v0.39.0 h1:jyyMd0LJyPUFb1Z7MS39uGbO4GZE2ZpxP1H2xsNbuaE= github.com/aiven/go-client-codegen v0.39.0/go.mod h1:FfbH32Xb+Hx5zeKTIug1Y8SfMeB+AKNRzxgrzkts2oA= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -346,6 +344,7 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -394,6 +393,8 @@ github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/gruntwork-io/terratest v0.47.2 h1:t6iWwsqJH7Gx0RwXleU/vjc+2c0JXRMdj3DxYXTBssQ= github.com/gruntwork-io/terratest v0.47.2/go.mod h1:LnYX8BN5WxUMpDr8rtD39oToSL4CBERWSCusbJ0d/64= +github.com/hamba/avro/v2 v2.26.0 h1:IaT5l6W3zh7K67sMrT2+RreJyDTllBGVJm4+Hedk9qE= +github.com/hamba/avro/v2 v2.26.0/go.mod h1:I8glyswHnpED3Nlx2ZdUe+4LJnCOOyiCzLMno9i/Uu0= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -469,6 +470,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= @@ -476,8 +479,9 @@ github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -515,6 +519,11 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= @@ -549,6 +558,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/internal/sdkprovider/service/kafkaschema/kafka_schema.go b/internal/sdkprovider/service/kafkaschema/kafka_schema.go index 4ecac0b73..558855520 100644 --- a/internal/sdkprovider/service/kafkaschema/kafka_schema.go +++ b/internal/sdkprovider/service/kafkaschema/kafka_schema.go @@ -10,6 +10,7 @@ import ( "github.com/aiven/aiven-go-client/v2" "github.com/aiven/go-client-codegen/handler/kafkaschemaregistry" + "github.com/hamba/avro/v2" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" @@ -46,10 +47,11 @@ var aivenKafkaSchemaSchema = map[string]*schema.Schema{ Type: schema.TypeString, Optional: true, ForceNew: true, - Description: "Kafka Schema configuration type. Defaults to AVRO. Possible values are AVRO, JSON, " + - "and PROTOBUF.", - Default: "AVRO", - ValidateFunc: validation.StringInSlice([]string{"AVRO", "JSON", "PROTOBUF"}, false), + Description: userconfig. + Desc("Kafka Schema configuration type. Defaults to AVRO"). + PossibleValuesString(kafkaschemaregistry.SchemaTypeChoices()...).Build(), + Default: kafkaschemaregistry.SchemaTypeAvro, + ValidateFunc: validation.StringInSlice(kafkaschemaregistry.SchemaTypeChoices(), false), DiffSuppressFunc: func(_, oldValue, _ string, d *schema.ResourceData) bool { // This field can't be retrieved once resource is created. // That produces a diff on plan on resource import. @@ -280,26 +282,42 @@ func resourceKafkaSchemaDelete(ctx context.Context, d *schema.ResourceData, m in } func resourceKafkaSchemaCustomizeDiff(ctx context.Context, d *schema.ResourceDiff, m interface{}) error { - client := m.(*aiven.Client) + client, err := common.GenClient() + if err != nil { + return err + } + + schemaType := kafkaschemaregistry.SchemaType(d.Get("schema_type").(string)) + schemaPayload := d.Get("schema").(string) + if schemaType == kafkaschemaregistry.SchemaTypeAvro { + _, err = avro.Parse(schemaPayload) + if err != nil { + return fmt.Errorf("schema validation error: %w", err) + } + } // no previous version: allow the diff, nothing to check compatibility against if _, ok := d.GetOk("version"); !ok { return nil } - if compatible, err := client.KafkaSubjectSchemas.Validate( + compatible, err := client.ServiceSchemaRegistryCompatibility( ctx, d.Get("project").(string), d.Get("service_name").(string), d.Get("subject_name").(string), d.Get("version").(int), - aiven.KafkaSchemaSubject{ - Schema: d.Get("schema").(string), - SchemaType: d.Get("schema_type").(string), + &kafkaschemaregistry.ServiceSchemaRegistryCompatibilityIn{ + Schema: schemaPayload, + SchemaType: schemaType, }, - ); err != nil { + ) + + if err != nil { return fmt.Errorf("unable to check schema validity: %w", err) - } else if !compatible { + } + + if !compatible { return fmt.Errorf("schema is not compatible with previous version") } diff --git a/internal/sdkprovider/service/kafkaschema/kafka_schema_test.go b/internal/sdkprovider/service/kafkaschema/kafka_schema_test.go index 55ccfbe27..3e9e55d57 100644 --- a/internal/sdkprovider/service/kafkaschema/kafka_schema_test.go +++ b/internal/sdkprovider/service/kafkaschema/kafka_schema_test.go @@ -548,3 +548,38 @@ func testAccCheckAivenKafkaSchemaAttributes(n string) resource.TestCheckFunc { return nil } } + +const invalidAvroSchemaConfig = ` +resource "aiven_kafka_schema" "foo" { + project = "foo" + service_name = "bar" + subject_name = "baz" + + schema = <