Ejemplo n.º 1
0
        public static void RegisterIncompatibleSchema(string server)
        {
            var topicName = Guid.NewGuid().ToString();

            var testSchema1 =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            var sr = new CachedSchemaRegistryClient(new Dictionary <string, object> {
                { "schema.registry.url", server }
            });

            var subject = sr.ConstructKeySubjectName(topicName, "Confluent.Kafka.Examples.AvroSpecific.User");
            var id      = sr.RegisterSchemaAsync(subject, testSchema1).Result;

            var testSchema2 = // incompatible with testSchema1
                              "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                              "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                              "nt\",\"null\"]},{\"name\":\"favorite_shape\",\"type\":[\"string\",\"null\"]}]}";

            Assert.False(sr.IsCompatibleAsync(subject, testSchema2).Result);

            Assert.Throws <AggregateException>(() => sr.RegisterSchemaAsync(subject, testSchema2).Result);

            Assert.True(sr.GetAllSubjectsAsync().Result.Contains(subject));
        }
Ejemplo n.º 2
0
        public static void JsonWithReferences(Config config)
        {
            var srInitial = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = config.Server
            });
            var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = config.Server
            });
            var topicName      = Guid.NewGuid().ToString();
            var subjectInitial = SubjectNameStrategy.Topic.ConstructValueSubjectName(topicName, null);
            var subject1       = SubjectNameStrategy.Topic.ConstructValueSubjectName(topicName + "1", null);
            var subject2       = SubjectNameStrategy.Topic.ConstructValueSubjectName(topicName + "2", null);

            // Test there are no errors (exceptions) registering a schema that references another.
            var id1  = srInitial.RegisterSchemaAsync(subject1, new Schema(S1, SchemaType.Json)).Result;
            var s1   = srInitial.GetLatestSchemaAsync(subject1).Result;
            var refs = new List <SchemaReference> {
                new SchemaReference("https://example.com/geographical-location.schema.json", subject1, s1.Version)
            };
            var id2 = srInitial.RegisterSchemaAsync(subject2, new Schema(S2, refs, SchemaType.Json)).Result;

            // In fact, it seems references are not checked server side.

            var latestSchema = sr.GetLatestSchemaAsync(subject2).Result;
        }
Ejemplo n.º 3
0
        public static void GetSubjectVersions(Config config)
        {
            var topicName = Guid.NewGuid().ToString();

            var testSchema1 =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            var testSchema2 = // compatible with testSchema1
                              "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                              "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                              "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}," +
                              "{\"name\":\"favorite_shape\",\"type\":[\"string\",\"null\"], \"default\": \"square\"}]}";

            var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = config.Server
            });

            var subject = sr.ConstructValueSubjectName(topicName);
            var id1     = sr.RegisterSchemaAsync(subject, testSchema1).Result;
            var id2     = sr.RegisterSchemaAsync(subject, testSchema2).Result;

            var versions = sr.GetSubjectVersionsAsync(subject).Result;

            Assert.Equal(versions.Count, 2);
        }
        public static void GetAllSubjects(Config config)
        {
            var topicName = Guid.NewGuid().ToString();

            var testSchema1 =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = config.Server
            });

            var subjectsBefore = sr.GetAllSubjectsAsync().Result;

            var subject = SubjectNameStrategy.Topic.ConstructKeySubjectName(topicName, null);
            var id      = sr.RegisterSchemaAsync(subject, testSchema1).Result;

            var subjectsAfter = sr.GetAllSubjectsAsync().Result;

            Assert.Equal(1, subjectsAfter.Count - subjectsBefore.Count);

            sr.RegisterSchemaAsync(subject, testSchema1).Wait();

            var subjectsAfter2 = sr.GetAllSubjectsAsync().Result;

            Assert.Equal(subjectsAfter.Count, subjectsAfter2.Count);

            Assert.True(subjectsAfter2.Contains(subject));
        }
Ejemplo n.º 5
0
        public static void AvroWithReferences(Config config)
        {
            var srClient = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = config.Server
            });
            Schema schema1 = new Schema(@"{""type"":""record"",""name"":""EventA"",""namespace"":""Kafka.Avro.Examples"",""fields"":[{""name"":""EventType"",""type"":""string""},{""name"":""EventId"",""type"":""string""},{""name"":""OccuredOn"",""type"":""long""},{""name"":""A"",""type"":""string""}]}", SchemaType.Avro);
            Schema schema2 = new Schema(@"{""type"":""record"",""name"":""EventB"",""namespace"":""Kafka.Avro.Examples"",""fields"":[{""name"":""EventType"",""type"":""string""},{""name"":""EventId"",""type"":""string""},{""name"":""OccuredOn"",""type"":""long""},{""name"":""B"",""type"":""long""}]}", SchemaType.Avro);
            var    id1     = srClient.RegisterSchemaAsync("events-a", schema1).Result;
            var    id2     = srClient.RegisterSchemaAsync("events-b", schema2).Result;

            var             avroUnion   = @"[""Kafka.Avro.Examples.EventA"",""Kafka.Avro.Examples.EventB""]";
            Schema          unionSchema = new Schema(avroUnion, SchemaType.Avro);
            SchemaReference reference   = new SchemaReference(
                "Kafka.Avro.Examples.EventA",
                "events-a",
                1);

            unionSchema.References.Add(reference);
            reference = new SchemaReference(
                "Kafka.Avro.Examples.EventB",
                "events-b",
                1);
            unionSchema.References.Add(reference);

            var id3 = srClient.RegisterSchemaAsync("events-value", unionSchema).Result;

            Assert.NotEqual(0, id3);
        }
        public static void FillTheCache(Config config)
        {
            const int capacity = 16;

            const string testSchema =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            var srConfig = new SchemaRegistryConfig
            {
                Url = config.Server,
                RequestTimeoutMs = 3000,
                MaxCachedSchemas = capacity
            };

            var sr = new CachedSchemaRegistryClient(srConfig);

            var registerCount = capacity + 10;

            var subjects = new List <string>();
            var ids      = new List <int>();

            // test is that this does not throw. Also, inspect in debugger.
            for (int i = 0; i < registerCount; ++i)
            {
                var topicName = Guid.NewGuid().ToString();
                var subject   = sr.ConstructValueSubjectName(topicName);
                subjects.Add(subject);

                var id = sr.RegisterSchemaAsync(subject, testSchema).Result;
                ids.Add(id);
            }
        }
        public static void RegisterNormalizedSchema(Config config)
        {
            var topicName = Guid.NewGuid().ToString();

            var testSchema1 =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":{\"type\": \"string\"}},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";
            var normalized =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = config.Server
            });

            var subject = SubjectNameStrategy.Topic.ConstructKeySubjectName(topicName, "Confluent.Kafka.Examples.AvroSpecific.User");

            Assert.Equal(topicName + "-key", subject);

            var id1    = sr.RegisterSchemaAsync(subject, testSchema1, true).Result;
            var id2    = sr.GetSchemaIdAsync(subject, testSchema1, true).Result;
            var schema = sr.GetSchemaAsync(id2).Result;

            Assert.Equal(id1, id2);
            Assert.Equal(normalized, schema);
        }
Ejemplo n.º 8
0
        public static void IsCompatible(string server)
        {
            var topicName = Guid.NewGuid().ToString();

            var testSchema1 =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            var sr = new CachedSchemaRegistryClient(new Dictionary <string, object> {
                { "schema.registry.url", server }
            });

            var subject = sr.ConstructKeySubjectName(topicName, "Confluent.Kafka.Examples.AvroSpecific.User");
            var id      = sr.RegisterSchemaAsync(subject, testSchema1).Result;

            var testSchema2 = // incompatible with testSchema1
                              "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                              "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                              "nt\",\"null\"]},{\"name\":\"favorite_shape\",\"type\":[\"string\",\"null\"]}]}";

            Assert.False(sr.IsCompatibleAsync(subject, testSchema2).Result);
            Assert.True(sr.IsCompatibleAsync(subject, testSchema1).Result);

            // Note: backwards / forwards compatibility scenarios are not tested here. This is really just testing the API call.
        }
Ejemplo n.º 9
0
        public static void FillTheCache(string server)
        {
            const int capacity = 16;

            const string testSchema =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            var config = new Dictionary <string, object>
            {
                { "schema.registry.url", server },
                { "schema.registry.connection.timeout.ms", 3000 },
                { "schema.registry.max.cached.schemas", capacity }
            };

            var sr = new CachedSchemaRegistryClient(config);

            var registerCount = capacity + 10;

            var subjects = new List <string>();
            var ids      = new List <int>();

            // test is that this does not throw. Also, inspect in debugger.
            for (int i = 0; i < registerCount; ++i)
            {
                var topicName = Guid.NewGuid().ToString();
                var subject   = sr.ConstructValueSubjectName(topicName);
                subjects.Add(subject);

                var id = sr.RegisterSchemaAsync(subject, testSchema).Result;
                ids.Add(id);
            }
        }
Ejemplo n.º 10
0
        public static void GetId(Config config)
        {
            var topicName = Guid.NewGuid().ToString();

            var testSchema1 =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                SchemaRegistryUrl = config.Server
            });

            var subject = sr.ConstructKeySubjectName(topicName);
            var id      = sr.RegisterSchemaAsync(subject, testSchema1).Result;
            var id2     = sr.GetSchemaIdAsync(subject, testSchema1).Result;

            Assert.Equal(id, id2);

            Assert.Throws <SchemaRegistryException>(() =>
            {
                try
                {
                    sr.GetSchemaIdAsync(subject, "{\"type\": \"string\"}").Wait();
                }
                catch (AggregateException e)
                {
                    throw e.InnerException;
                }
            });
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Creates a serializer.
        /// </summary>
        /// <param name="registryConfiguration">
        /// Schema Registry configuration. Using the <see cref="SchemaRegistryConfig" /> class is
        /// highly recommended.
        /// </param>
        /// <param name="registerAutomatically">
        /// When to automatically register schemas that match the type being serialized.
        /// </param>
        /// <param name="schemaBuilder">
        /// The schema builder to use to create a schema for a C# type when registering automatically.
        /// If none is provided, the default schema builder will be used.
        /// </param>
        /// <param name="schemaReader">
        /// The JSON schema reader to use to convert schemas received from the registry into abstract
        /// representations. If none is provided, the default schema reader will be used.
        /// </param>
        /// <param name="schemaWriter">
        /// The JSON schema writer to use to convert abstract schema representations when registering
        /// automatically. If none is provided, the default schema writer will be used.
        /// </param>
        /// <param name="serializerBuilder">
        /// The deserializer builder to use to build serialization functions for C# types. If none
        /// is provided, the default serializer builder will be used.
        /// </param>
        /// <param name="subjectNameBuilder">
        /// A function that determines the subject name given the topic name and a component type
        /// (key or value). If none is provided, the default "{topic name}-{component}" naming
        /// convention will be used.
        /// </param>
        /// <param name="tombstoneBehavior">
        /// The behavior of the serializer on tombstone records.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Thrown when the registry configuration is null.
        /// </exception>
        public AsyncSchemaRegistrySerializer(
            IEnumerable <KeyValuePair <string, string> > registryConfiguration,
            AutomaticRegistrationBehavior registerAutomatically = AutomaticRegistrationBehavior.Never,
            Abstract.ISchemaBuilder schemaBuilder                  = null,
            IJsonSchemaReader schemaReader                         = null,
            IJsonSchemaWriter schemaWriter                         = null,
            IBinarySerializerBuilder serializerBuilder             = null,
            Func <SerializationContext, string> subjectNameBuilder = null,
            TombstoneBehavior tombstoneBehavior                    = TombstoneBehavior.None
            )
        {
            if (registryConfiguration == null)
            {
                throw new ArgumentNullException(nameof(registryConfiguration));
            }

            if (tombstoneBehavior != TombstoneBehavior.None && default(T) != null)
            {
                throw new UnsupportedTypeException(typeof(T), $"{typeof(T)} cannot represent tombstone values.");
            }

            RegisterAutomatically = registerAutomatically;
            SchemaBuilder         = schemaBuilder ?? new Abstract.SchemaBuilder();
            SchemaReader          = schemaReader ?? new JsonSchemaReader();
            SchemaWriter          = schemaWriter ?? new JsonSchemaWriter();
            SerializerBuilder     = serializerBuilder ?? new BinarySerializerBuilder();
            SubjectNameBuilder    = subjectNameBuilder ??
                                    (c => $"{c.Topic}-{(c.Component == MessageComponentType.Key ? "key" : "value")}");
            TombstoneBehavior = tombstoneBehavior;

            _cache = new Dictionary <string, Task <Func <T, byte[]> > >();

            _register = async(subject, json) =>
            {
                using (var registry = new CachedSchemaRegistryClient(registryConfiguration))
                {
                    return(await registry.RegisterSchemaAsync(subject, new Schema(json, SchemaType.Avro)).ConfigureAwait(false));
                }
            };

            _resolve = async subject =>
            {
                using (var registry = new CachedSchemaRegistryClient(registryConfiguration))
                {
                    var schema = await registry.GetLatestSchemaAsync(subject).ConfigureAwait(false);

                    if (schema.SchemaType != SchemaType.Avro)
                    {
                        throw new UnsupportedSchemaException(null, $"The latest schema with subject {subject} is not an Avro schema.");
                    }

                    return(schema);
                }
            };
        }
Ejemplo n.º 12
0
        public static void IsCompatible_Topic(Config config)
        {
            var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = config.Server
            });

            var testSchema1 =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            var testSchema2 = // incompatible with testSchema1
                              "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                              "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                              "nt\",\"null\"]},{\"name\":\"favorite_shape\",\"type\":[\"string\",\"null\"]}]}";


            // case 1: record specified.
            var topicName = Guid.NewGuid().ToString();
            var subject   = SubjectNameStrategy.Topic.ConstructKeySubjectName(topicName, "Confluent.Kafka.Examples.AvroSpecific.User");

            sr.RegisterSchemaAsync(subject, testSchema1).Wait();

            Assert.False(sr.IsCompatibleAsync(subject, testSchema2).Result);
            Assert.True(sr.IsCompatibleAsync(subject, testSchema1).Result);


            // case 2: record not specified.
            topicName = Guid.NewGuid().ToString();
            subject   = SubjectNameStrategy.Topic.ConstructKeySubjectName(topicName, null);

            sr.RegisterSchemaAsync(subject, testSchema1).Wait();

            Assert.False(sr.IsCompatibleAsync(subject, testSchema2).Result);
            Assert.True(sr.IsCompatibleAsync(subject, testSchema1).Result);


            // Note: backwards / forwards compatibility scenarios are not tested here. This is really just testing the API call.
        }
Ejemplo n.º 13
0
        private static void Main()
        {
            var schemaRegistryConfig = new Dictionary <string, object>
            {
                { "schema.registry.url", "localhost:8081" },
                { "schema.registry.connection.timeout.ms", 5000 }, // optional
                { "schema.registry.max.cached.schemas", 10 } // optional
            };

            var producerConfig = new Dictionary <string, object>
            {
                { "schema.registry.url", "localhost:8081" },
                { "bootstrap.servers", "localhost:9092" }
            };

            Console.WriteLine("Producer ready...");

            using (var schemaRegistryClient = new CachedSchemaRegistryClient(schemaRegistryConfig))
            {
                var s = (RecordSchema)Avro.Schema.Parse(File.ReadAllText(@"C:\PROJECTDATA\PLAYGROUND\PlayingWithKafka\Kafka\Organisation.asvc"));
                schemaRegistryClient.RegisterSchemaAsync("organisation-topic-schema", s.ToString());

                using (var producer = new Producer <string, Organisation>(producerConfig, new AvroSerializer <string>(), new AvroSerializer <Organisation>()))
                {
                    var cancelled = false;

                    Console.CancelKeyPress += (_, e) =>
                    {
                        e.Cancel  = true; // prevent the process from terminating.
                        cancelled = true;
                    };

                    while (!cancelled)
                    {
                        var fixture = new Fixture();

                        var organisation = fixture.Build <Organisation>().Create();

                        var deliveryReport = producer.ProduceAsync("organisation-topic", organisation.id, organisation);

                        var result = deliveryReport.Result; // synchronously waits for message to be produced.

                        Console.WriteLine($"Partition: {result.Partition}, Offset: {result.Offset}");

                        Thread.Sleep(500);
                    }
                }
            }
        }
Ejemplo n.º 14
0
        public static void Failover(Config config)
        {
            var testSchema =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            using (var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = $"{config.Server},http://localhost:65432"
            }))
            {
                var topicName = Guid.NewGuid().ToString();
                var subject   = SubjectNameStrategy.Topic.ConstructKeySubjectName(topicName, null);
                var id        = sr.RegisterSchemaAsync(subject, testSchema, false).Result;
                var id2       = sr.GetSchemaIdAsync(subject, testSchema, false).Result;
                Assert.Equal(id, id2);
            }

            using (var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = $"http://localhost:65432,{config.Server}"
            }))
            {
                var topicName = Guid.NewGuid().ToString();
                var subject   = SubjectNameStrategy.Topic.ConstructKeySubjectName(topicName, null);
                var id        = sr.RegisterSchemaAsync(subject, testSchema, false).Result;
                var id2       = sr.GetSchemaIdAsync(subject, testSchema, false).Result;
                Assert.Equal(id, id2);
            }

            using (var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = $"http://localhost:65432,http://localhost:65431"
            }))
            {
                var topicName = Guid.NewGuid().ToString();
                var subject   = SubjectNameStrategy.Topic.ConstructKeySubjectName(topicName, null);

                Assert.Throws <HttpRequestException>(() =>
                {
                    try
                    {
                        sr.RegisterSchemaAsync(subject, testSchema).Wait();
                    }
                    catch (AggregateException e)
                    {
                        throw e.InnerException;
                    }
                });
            }
        }
Ejemplo n.º 15
0
        public static void SslAuth(Config config)
        {
            var testSchema1 =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            // 1. valid configuration cases

            // 1.1. using SSL valid certificate.
            var conf = new SchemaRegistryConfig
            {
                Url = config.ServerWithSsl,
                SslKeystoreLocation = config.KeystoreLocation,
                SslKeystorePassword = config.KeystorePassword,
                SslCaLocation       = config.CaLocation,
                EnableSslCertificateVerification = bool.Parse(config.EnableSslCertificateVerification),
            };

            // some sanity checking of strongly typed config property name mappings.
            Assert.Equal(config.ServerWithSsl, conf.Get("schema.registry.url"));

            using (var sr = new CachedSchemaRegistryClient(conf))
            {
                var topicName = Guid.NewGuid().ToString();
                var subject   = SubjectNameStrategy.Topic.ToDelegate()(new SerializationContext(MessageComponentType.Value, topicName), null);
                var id        = sr.RegisterSchemaAsync(subject, testSchema1).Result;
                var schema    = sr.GetLatestSchemaAsync(subject).Result;
                Assert.Equal(schema.Id, id);
            }

            // try to connect with invalid SSL config. shouldn't work.
            Assert.Throws <HttpRequestException>(() =>
            {
                var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                    Url = config.ServerWithSsl
                });
                var topicName = Guid.NewGuid().ToString();
                var subject   = SubjectNameStrategy.Topic.ConstructValueSubjectName(topicName, null);
                try
                {
                    var id = sr.RegisterSchemaAsync(subject, testSchema1).Result;
                }
                catch (Exception e)
                {
                    throw e.InnerException;
                }
            });
        }
        public static void RegisterSameSchemaTwice(string server)
        {
            var topicName = Guid.NewGuid().ToString();

            var testSchema1 =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            var sr = new CachedSchemaRegistryClient(new Dictionary <string, object> {
                { "schema.registry.url", server }
            });

            var subject = sr.ConstructKeySubjectName(topicName);

            Assert.Equal(topicName + "-key", subject);

            var id1 = sr.RegisterSchemaAsync(subject, testSchema1).Result;
            var id2 = sr.RegisterSchemaAsync(subject, testSchema1).Result;

            Assert.Equal(id1, id2);

            Assert.True(sr.GetAllSubjectsAsync().Result.Contains(subject));
        }
Ejemplo n.º 17
0
        public static void Json(Config config)
        {
            var srInitial = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = config.Server
            });
            var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = config.Server
            });
            var topicName      = Guid.NewGuid().ToString();
            var subjectInitial = SubjectNameStrategy.Topic.ConstructValueSubjectName(topicName, null);
            var subject        = SubjectNameStrategy.Topic.ConstructValueSubjectName(topicName + "2", null);

            var id1     = srInitial.RegisterSchemaAsync(subjectInitial, new Schema(TestJsonSchema, SchemaType.Json)).Result;
            var schema1 = sr.GetSchemaAsync(id1).Result; // use a different sr instance to ensure a cached value is not read.

            Assert.Equal(SchemaType.Json, schema1.SchemaType);
            Assert.NotNull(schema1.SchemaString); // SR munges the schema (whitespace), so in general this won't equal the registered schema.

            // check that the id of the schema just registered can be retrieved.
            var id = sr.GetSchemaIdAsync(subjectInitial, new Schema(schema1.SchemaString, SchemaType.Json)).Result;

            Assert.Equal(id1, id);

            // re-register the munged schema (to a different subject) and check that it is not re-munged.
            var id2     = sr.RegisterSchemaAsync(subject, schema1).Result;
            var schema2 = sr.GetSchemaAsync(id2).Result;

            Assert.Equal(schema1.SchemaString, schema2.SchemaString);
            Assert.Equal(schema1.SchemaType, schema2.SchemaType);

            // compatibility
            var compat = sr.IsCompatibleAsync(subject, schema2).Result;

            Assert.True(compat);
            var avroSchema =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            var compat2 = sr.IsCompatibleAsync(subject, avroSchema).Result;

            Assert.False(compat2);
            var compat3 = sr.IsCompatibleAsync(subject, new Schema(avroSchema, SchemaType.Avro)).Result;

            Assert.False(compat3);
        }
        public static void ProtobufWithReferences(Config config)
        {
            var srInitial = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = config.Server
            });
            var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = config.Server
            });
            var testSchemaBase64 = Confluent.Kafka.Examples.Protobuf.Person.Descriptor.File.SerializedData.ToBase64();
            var topicName        = Guid.NewGuid().ToString();
            var subjectInitial   = SubjectNameStrategy.Topic.ConstructValueSubjectName(topicName, null);
            var subject          = SubjectNameStrategy.Topic.ConstructValueSubjectName(topicName + "2", null);

            // check that registering a base64 protobuf schema works.
            var id1 = srInitial.RegisterSchemaAsync(subjectInitial, new Schema(testSchemaBase64, SchemaType.Protobuf)).Result;

            var sc = srInitial.GetSchemaAsync(id1).Result;
        }
Ejemplo n.º 19
0
        private static void GetSchemaBySubjectAndVersion(Dictionary <string, object> config)
        {
            var topicName = Guid.NewGuid().ToString();

            var testSchema1 =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            var sr = new CachedSchemaRegistryClient(config);

            var subject = sr.ConstructValueSubjectName(topicName, "Confluent.Kafka.Examples.AvroSpecific.User");
            var id      = sr.RegisterSchemaAsync(subject, testSchema1).Result;

            var schema       = sr.GetLatestSchemaAsync(subject).Result;
            var schemaString = sr.GetSchemaAsync(subject, schema.Version).Result;

            Assert.Equal(schemaString, testSchema1);
        }
Ejemplo n.º 20
0
    public async Task AvroExampleAsync(string ksqlDbUrl)
    {
        var schemaRegistryConfig = new SchemaRegistryConfig
        {
            Url = "http://localhost:8081"
        };

        using var schemaRegistry = new CachedSchemaRegistryClient(schemaRegistryConfig);

        var schema = IoTSensor._SCHEMA.ToString();

        var subject = "IoTSensors-value";

        var registrationResult = await schemaRegistry.RegisterSchemaAsync(subject, schema);

        //http://localhost:8081/subjects/IoTSensors-value/versions/latest/schema
        var latestSchema = await schemaRegistry.GetLatestSchemaAsync(subject);

        var httpClientFactory = new HttpClientFactory(new Uri(ksqlDbUrl));
        var restApiClient     = new KSqlDbRestApiProvider(httpClientFactory);

        EntityCreationMetadata metadata = new()
        {
            EntityName  = "avroSensors",
            KafkaTopic  = "IoTSensors",
            ValueFormat = SerializationFormats.Avro,
            Partitions  = 1,
            Replicas    = 1
        };

        var httpResponseMessage = await restApiClient.CreateStreamAsync <IoTSensor>(metadata, ifNotExists : false)
                                  .ConfigureAwait(false);

        var httpResponse = await httpResponseMessage.Content.ReadAsStringAsync();

        Console.WriteLine(httpResponse);

        // Stream Name         | Kafka Topic | Key Format | Value Format | Windowed
        //   ------------------------------------------------------------------------------------------------------
        // AVROSENSORS | IoTSensors | KAFKA | AVRO | false
    }
}
Ejemplo n.º 21
0
        public static void GetSchemaById(string server)
        {
            var topicName = Guid.NewGuid().ToString();

            var testSchema1 =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            var sr = new CachedSchemaRegistryClient(new Dictionary <string, object> {
                { "schema.registry.url", server }
            });

            var subject = sr.ConstructValueSubjectName(topicName);
            var id      = sr.RegisterSchemaAsync(subject, testSchema1).Result;

            var schema = sr.GetSchemaAsync(id).Result;

            Assert.Equal(schema, testSchema1);
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Creates a serializer.
        /// </summary>
        /// <param name="registryConfiguration">
        /// Schema Registry configuration. Using the <see cref="SchemaRegistryConfig" /> class is
        /// highly recommended.
        /// </param>
        /// <param name="registerAutomatically">
        /// Whether to automatically register schemas that match the type being serialized.
        /// </param>
        /// <param name="schemaBuilder">
        /// The schema builder to use to create a schema for a C# type when registering automatically.
        /// If none is provided, the default schema builder will be used.
        /// </param>
        /// <param name="schemaReader">
        /// The JSON schema reader to use to convert schemas received from the registry into abstract
        /// representations. If none is provided, the default schema reader will be used.
        /// </param>
        /// <param name="schemaWriter">
        /// The JSON schema writer to use to convert abstract schema representations when registering
        /// automatically. If none is provided, the default schema writer will be used.
        /// </param>
        /// <param name="serializerBuilder">
        /// The deserializer builder to use to build serialization functions for C# types. If none
        /// is provided, the default serializer builder will be used.
        /// </param>
        /// <param name="subjectNameBuilder">
        /// A function that determines the subject name given the topic name and a component type
        /// (key or value). If none is provided, the default "{topic name}-{component}" naming
        /// convention will be used.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Thrown when the registry configuration is null.
        /// </exception>
        public AsyncSchemaRegistrySerializer(
            IEnumerable <KeyValuePair <string, string> > registryConfiguration,
            bool registerAutomatically                             = false,
            Abstract.ISchemaBuilder?schemaBuilder                  = null,
            IJsonSchemaReader?schemaReader                         = null,
            IJsonSchemaWriter?schemaWriter                         = null,
            IBinarySerializerBuilder?serializerBuilder             = null,
            Func <SerializationContext, string>?subjectNameBuilder = null
            )
        {
            if (registryConfiguration == null)
            {
                throw new ArgumentNullException(nameof(registryConfiguration));
            }

            RegisterAutomatically = registerAutomatically;
            SchemaBuilder         = schemaBuilder ?? new Abstract.SchemaBuilder();
            SchemaReader          = schemaReader ?? new JsonSchemaReader();
            SchemaWriter          = schemaWriter ?? new JsonSchemaWriter();
            SerializerBuilder     = serializerBuilder ?? new BinarySerializerBuilder();
            SubjectNameBuilder    = subjectNameBuilder ??
                                    (c => $"{c.Topic}-{(c.Component == MessageComponentType.Key ? "key" : "value")}");

            _cache = new ConcurrentDictionary <string, Task <Func <T, byte[]> > >();

            _register = async(subject, json) =>
            {
                using (var registry = new CachedSchemaRegistryClient(registryConfiguration))
                {
                    return(await registry.RegisterSchemaAsync(subject, json).ConfigureAwait(false));
                }
            };

            _resolve = async subject =>
            {
                using (var registry = new CachedSchemaRegistryClient(registryConfiguration))
                {
                    return(await registry.GetLatestSchemaAsync(subject).ConfigureAwait(false));
                }
            };
        }
        public static void GetSchemaById(Config config)
        {
            var topicName = Guid.NewGuid().ToString();

            var testSchema1 =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = config.Server
            });

            var subject = SubjectNameStrategy.Topic.ConstructKeySubjectName(topicName, null);
            var id      = sr.RegisterSchemaAsync(subject, testSchema1).Result;

            var schema = sr.GetSchemaAsync(id).Result;

            Assert.Equal(schema.SchemaString, testSchema1);
            Assert.Empty(schema.References);
            Assert.Equal(schema.SchemaType, SchemaType.Avro);
        }
        /// <summary>
        /// Creates a serializer.
        /// </summary>
        /// <param name="registryConfiguration">
        /// Schema Registry configuration. Using the <see cref="SchemaRegistryConfig" /> class is
        /// highly recommended.
        /// </param>
        /// <param name="registerAutomatically">
        /// Whether to automatically register schemas that match the type being serialized.
        /// </param>
        /// <param name="schemaBuilder">
        /// A schema builder (used to build a schema for a C# type when registering automatically).
        /// If none is provided, the default schema builder will be used.
        /// </param>
        /// <param name="schemaReader">
        /// A JSON schema reader (used to convert schemas received from the registry into abstract
        /// representations). If none is provided, the default schema reader will be used.
        /// </param>
        /// <param name="schemaWriter">
        /// A JSON schema writer (used to convert abstract schema representations when registering
        /// automatically). If none is provided, the default schema writer will be used.
        /// </param>
        /// <param name="serializerBuilder">
        /// A deserializer builder (used to build serialization functions for C# types). If none is
        /// provided, the default serializer builder will be used.
        /// </param>
        /// <param name="subjectNameBuilder">
        /// A function that determines the subject name given the topic name and a component type
        /// (key or value). If none is provided, the default "{topic name}-{component}" naming
        /// convention will be used.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Thrown when the registry configuration is null.
        /// </exception>
        public AsyncSchemaRegistrySerializer(
            IEnumerable <KeyValuePair <string, string> > registryConfiguration,
            bool registerAutomatically                             = false,
            Abstract.ISchemaBuilder schemaBuilder                  = null,
            IJsonSchemaReader schemaReader                         = null,
            IJsonSchemaWriter schemaWriter                         = null,
            IBinarySerializerBuilder serializerBuilder             = null,
            Func <SerializationContext, string> subjectNameBuilder = null
            ) : this(
                registerAutomatically,
                schemaBuilder,
                schemaReader,
                schemaWriter,
                serializerBuilder,
                subjectNameBuilder
                )
        {
            if (registryConfiguration == null)
            {
                throw new ArgumentNullException(nameof(registryConfiguration));
            }

            _register = async(subject, json) =>
            {
                using (var registry = new CachedSchemaRegistryClient(registryConfiguration))
                {
                    return(await registry.RegisterSchemaAsync(subject, json).ConfigureAwait(false));
                }
            };

            _resolve = async subject =>
            {
                using (var registry = new CachedSchemaRegistryClient(registryConfiguration))
                {
                    return(await registry.GetLatestSchemaAsync(subject).ConfigureAwait(false));
                }
            };
        }
        public static void GetLatestSchema(Config config)
        {
            var topicName = Guid.NewGuid().ToString();

            var testSchema1 =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                SchemaRegistryUrl = config.Server
            });

            var subject = sr.ConstructValueSubjectName(topicName);
            var id      = sr.RegisterSchemaAsync(subject, testSchema1).Result;

            var schema = sr.GetLatestSchemaAsync(subject).Result;

            Assert.Equal(schema.Id, id);
            Assert.Equal(schema.Subject, subject);
            Assert.Equal(schema.Version, 1);
            Assert.Equal(schema.SchemaString, testSchema1);
        }
Ejemplo n.º 26
0
        public static void Protobuf(Config config)
        {
            var srInitial = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = config.Server
            });
            var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                Url = config.Server
            });
            var testSchemaBase64 = Confluent.Kafka.Examples.Protobuf.User.Descriptor.File.SerializedData.ToBase64();
            var topicName        = Guid.NewGuid().ToString();
            var subjectInitial   = SubjectNameStrategy.Topic.ConstructValueSubjectName(topicName, null);
            var subject          = SubjectNameStrategy.Topic.ConstructValueSubjectName(topicName + "2", null);

            // check that registering a base64 protobuf schema works.
            var id1     = srInitial.RegisterSchemaAsync(subjectInitial, new Schema(testSchemaBase64, SchemaType.Protobuf)).Result;
            var schema1 = sr.GetSchemaAsync(id1, "serialized").Result; // use a different sr instance to ensure a cached value is not read.

            Assert.Equal(SchemaType.Protobuf, schema1.SchemaType);
            Assert.NotNull(schema1.SchemaString); // SR slightly munges the schema as a result of moving to a text representation and back so can't check for equality.

            // check that the id of the schema just registered can be retrieved.
            var id = sr.GetSchemaIdAsync(subjectInitial, new Schema(schema1.SchemaString, SchemaType.Protobuf)).Result;

            Assert.Equal(id1, id);

            // re-register the munged schema (to a different subject) and check that it is not re-munged.
            var id2     = sr.RegisterSchemaAsync(subject, schema1).Result;
            var schema2 = sr.GetSchemaAsync(id2, "serialized").Result;

            Assert.Equal(schema1.SchemaString, schema2.SchemaString);
            Assert.Equal(schema1.SchemaType, schema2.SchemaType);

            // This sequence of operations is designed to test caching behavior (and two alternat schema getting methods).
            var schemaAsText        = sr.GetSchemaAsync(id2).Result;
            var schemaAsSerialized  = sr.GetSchemaAsync(id2, "serialized").Result;
            var schemaAsText2       = sr.GetSchemaAsync(id2).Result;
            var schemaAsSerialized2 = sr.GetSchemaAsync(id2, "serialized").Result;
            var latestSchema        = sr.GetLatestSchemaAsync(subject).Result;                           // should come back as text.
            var schemaAsSerialized3 = sr.GetSchemaAsync(id2, "serialized").Result;
            var latestSchema2       = sr.GetRegisteredSchemaAsync(subject, latestSchema.Version).Result; // should come back as text.

            Assert.Equal(schema1.SchemaString, schemaAsSerialized.SchemaString);
            Assert.Equal(SchemaType.Protobuf, schemaAsSerialized.SchemaType);
            Assert.Empty(schemaAsSerialized.References);
            Assert.Equal(schema1.SchemaString, schemaAsSerialized2.SchemaString);
            Assert.Equal(schema1.SchemaString, schemaAsSerialized3.SchemaString);
            Assert.NotEqual(schema1.SchemaString, schemaAsText.SchemaString);
            Assert.Equal(schemaAsText.SchemaString, schemaAsText2.SchemaString);
            Assert.Equal(schemaAsText.SchemaString, latestSchema.SchemaString);
            Assert.Equal(schemaAsText.SchemaString, latestSchema2.SchemaString);
            Assert.Equal(SchemaType.Protobuf, schemaAsText.SchemaType);
            Assert.Empty(schemaAsText2.References);

            // compatibility
            var compat = sr.IsCompatibleAsync(subject, schema2).Result;

            Assert.True(compat);
            var avroSchema =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";
            var compat2 = sr.IsCompatibleAsync(subject, avroSchema).Result;

            Assert.False(compat2);
            var compat3 = sr.IsCompatibleAsync(subject, new Schema(avroSchema, SchemaType.Avro)).Result;

            Assert.False(compat3);

            // invalid type
            Assert.ThrowsAny <Exception>(() => {
                sr.RegisterSchemaAsync(SubjectNameStrategy.Topic.ConstructKeySubjectName(topicName + "3", null), new Schema(avroSchema, SchemaType.Protobuf)).Wait();
            });
        }
Ejemplo n.º 27
0
        private static void BMSpecificProduceConsume(string bootstrapServers, string schemaRegistryServers)
        {
            var producerConfig = new ProducerConfig {
                BootstrapServers = bootstrapServers
            };

            var schemaRegistryConfig = new SchemaRegistryConfig
            {
                Url = schemaRegistryServers
            };

            var adminClientConfig = new AdminClientConfig
            {
                BootstrapServers = bootstrapServers
            };

            var topic = Guid.NewGuid().ToString();

            Console.Error.WriteLine($"topic: {topic}");

            using (var adminClient = new AdminClientBuilder(adminClientConfig).Build())
            {
                adminClient.CreateTopicsAsync(
                    new List <TopicSpecification> {
                    new TopicSpecification {
                        Name = topic, NumPartitions = 1, ReplicationFactor = 1
                    }
                }).Wait();
            }

            var    srClient = new CachedSchemaRegistryClient(schemaRegistryConfig);
            Schema schema1  = new Schema(EventA._SCHEMA.ToString(), SchemaType.Avro);
            Schema schema2  = new Schema(EventB._SCHEMA.ToString(), SchemaType.Avro);
            var    id1      = srClient.RegisterSchemaAsync("events-a", schema1).Result;
            var    id2      = srClient.RegisterSchemaAsync("events-b", schema2).Result;

            var             avroUnion   = @"[""Confluent.Kafka.Examples.AvroSpecific.EventA"",""Confluent.Kafka.Examples.AvroSpecific.EventB""]";
            Schema          unionSchema = new Schema(avroUnion, SchemaType.Avro);
            SchemaReference reference   = new SchemaReference(
                "Confluent.Kafka.Examples.AvroSpecific.EventA",
                "events-a",
                srClient.GetLatestSchemaAsync("events-a").Result.Version);

            unionSchema.References.Add(reference);
            reference = new SchemaReference(
                "Confluent.Kafka.Examples.AvroSpecific.EventB",
                "events-b",
                srClient.GetLatestSchemaAsync("events-b").Result.Version);
            unionSchema.References.Add(reference);

            var id3 = srClient.RegisterSchemaAsync($"{topic}-value", unionSchema).Result;

            AvroSerializerConfig avroSerializerConfig = new AvroSerializerConfig {
                AutoRegisterSchemas = false, UseLatestSchemaVersion = true
            };

            using (var schemaRegistry = new CachedSchemaRegistryClient(schemaRegistryConfig))
                using (var producer =
                           new ProducerBuilder <string, ISpecificRecord>(producerConfig)
                           .SetKeySerializer(new AvroSerializer <string>(schemaRegistry))
                           .SetValueSerializer(new BmSpecificSerializerImpl <ISpecificRecord>(
                                                   schemaRegistry,
                                                   false,
                                                   1024,
                                                   SubjectNameStrategy.Topic.ToDelegate(),
                                                   true))
                           .Build())
                {
                    for (int i = 0; i < 3; ++i)
                    {
                        var eventA = new EventA
                        {
                            A         = "I'm event A",
                            EventId   = Guid.NewGuid().ToString(),
                            EventType = "EventType-A",
                            OccuredOn = DateTime.UtcNow.Ticks,
                        };

                        producer.ProduceAsync(topic, new Message <string, ISpecificRecord> {
                            Key = "DomainEvent", Value = eventA
                        }).Wait();
                    }

                    for (int i = 0; i < 3; ++i)
                    {
                        var eventB = new EventB
                        {
                            B         = 123456987,
                            EventId   = Guid.NewGuid().ToString(),
                            EventType = "EventType-B",
                            OccuredOn = DateTime.UtcNow.Ticks,
                        };

                        producer.ProduceAsync(topic, new Message <string, ISpecificRecord> {
                            Key = "DomainEvent", Value = eventB
                        }).Wait();
                    }

                    Assert.Equal(0, producer.Flush(TimeSpan.FromSeconds(10)));
                }

            var consumerConfig = new ConsumerConfig
            {
                BootstrapServers   = bootstrapServers,
                GroupId            = Guid.NewGuid().ToString(),
                SessionTimeoutMs   = 6000,
                AutoOffsetReset    = AutoOffsetReset.Earliest,
                EnablePartitionEof = true
            };

            using (var schemaRegistry = new CachedSchemaRegistryClient(schemaRegistryConfig))
                using (var consumer =
                           new ConsumerBuilder <string, GenericRecord>(consumerConfig)
                           .SetKeyDeserializer(new AvroDeserializer <string>(schemaRegistry).AsSyncOverAsync())
                           .SetValueDeserializer(new BmGenericDeserializerImpl(schemaRegistry).AsSyncOverAsync())
                           .SetErrorHandler((_, e) => Assert.True(false, e.Reason))
                           .Build())
                {
                    consumer.Subscribe(topic);

                    int i = 0;
                    while (true)
                    {
                        var record = consumer.Consume(TimeSpan.FromMilliseconds(100));
                        if (record == null)
                        {
                            continue;
                        }
                        if (record.IsPartitionEOF)
                        {
                            break;
                        }

                        Console.WriteLine(record.Message.Value["EventType"]);
                        i += 1;
                    }

                    Assert.Equal(6, i);

                    consumer.Close();
                }
        }
Ejemplo n.º 28
0
        public static void BasicAuth(Config config)
        {
            var testSchema1 =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            // 1. valid configuration cases

            // 1.1. credentials specified as USER_INFO.
            var conf = new SchemaRegistryConfig
            {
                Url = config.ServerWithAuth,
                BasicAuthCredentialsSource = AuthCredentialsSource.UserInfo,
                BasicAuthUserInfo          = $"{config.Username}:{config.Password}"
            };

            // some sanity checking of strongly typed config property name mappings.
            Assert.Equal(config.ServerWithAuth, conf.Get("schema.registry.url"));
            Assert.Equal("USER_INFO", conf.Get("schema.registry.basic.auth.credentials.source"));
            Assert.Equal($"{config.Username}:{config.Password}", conf.Get("schema.registry.basic.auth.user.info"));

            using (var sr = new CachedSchemaRegistryClient(conf))
            {
                var topicName = Guid.NewGuid().ToString();
                var subject   = SubjectNameStrategy.Topic.ToDelegate()(new SerializationContext(MessageComponentType.Value, topicName), null);
                var id        = sr.RegisterSchemaAsync(subject, testSchema1).Result;
                var schema    = sr.GetLatestSchemaAsync(subject).Result;
                Assert.Equal(schema.Id, id);
            }

            // 1.2. credentials specified as USER_INFO implicitly (and using strongly typed SchemaRegistryConfig)
            var conf2 = new SchemaRegistryConfig
            {
                Url = config.ServerWithAuth,
                BasicAuthUserInfo = $"{config.Username}:{config.Password}"
            };

            using (var sr = new CachedSchemaRegistryClient(conf2))
            {
                var topicName = Guid.NewGuid().ToString();
                var subject   = SubjectNameStrategy.Topic.ConstructValueSubjectName(topicName, null);
                var id        = sr.RegisterSchemaAsync(subject, testSchema1).Result;
                var schema    = sr.GetLatestSchemaAsync(subject).Result;
                Assert.Equal(schema.Id, id);
            }

            // 1.3. credentials specified as SASL_INHERIT.
            using (var sr = new CachedSchemaRegistryClient(
                       new Dictionary <string, string>
            {
                { "schema.registry.url", config.ServerWithAuth },
                { "schema.registry.basic.auth.credentials.source", "SASL_INHERIT" },
                { "sasl.username", config.Username },
                { "sasl.password", config.Password }
            }))
            {
                var topicName = Guid.NewGuid().ToString();
                var subject   = SubjectNameStrategy.Topic.ConstructValueSubjectName(topicName, null);
                var id        = sr.RegisterSchemaAsync(subject, testSchema1).Result;
                var schema    = sr.GetLatestSchemaAsync(subject).Result;
                Assert.Equal(schema.Id, id);
            }

            // 1.4. credentials specified as SASL_INHERIT via strongly typed config.
            var conf3 = new SchemaRegistryConfig {
                Url = config.ServerWithAuth
            };

            conf3.BasicAuthCredentialsSource = AuthCredentialsSource.SaslInherit;
            conf3.Set("sasl.username", config.Username);
            conf3.Set("sasl.password", config.Password);
            using (var sr = new CachedSchemaRegistryClient(conf3))
            {
                var topicName = Guid.NewGuid().ToString();
                var subject   = SubjectNameStrategy.Topic.ConstructValueSubjectName(topicName, null);
                var id        = sr.RegisterSchemaAsync(subject, testSchema1).Result;
                var schema    = sr.GetLatestSchemaAsync(subject).Result;
                Assert.Equal(schema.Id, id);
            }


            // 2. invalid configuration cases

            Assert.Throws <ArgumentException>(() =>
            {
                var sr = new CachedSchemaRegistryClient(new Dictionary <string, string>
                {
                    { "schema.registry.url", config.ServerWithAuth },
                    { "schema.registry.basic.auth.credentials.source", "SASL_INHERIT" },
                    { "schema.registry.basic.auth.user.info", $"{config.Username:config.Password}" }
                });
            });

            Assert.Throws <ArgumentException>(() =>
            {
                var sr = new CachedSchemaRegistryClient(new Dictionary <string, string>
                {
                    { "schema.registry.url", config.ServerWithAuth },
                    { "schema.registry.basic.auth.credentials.source", "UBUTE_SOURCE" }
                });
            });

            Assert.Throws <ArgumentException>(() =>
            {
                var sr = new CachedSchemaRegistryClient(new Dictionary <string, string>
                {
                    { "schema.registry.url", config.ServerWithAuth },
                    { "schema.registry.basic.auth.credentials.source", "NONE" },
                    { "schema.registry.basic.auth.user.info", $"{config.Username:config.Password}" }
                });
            });

            // connect to authenticating without credentials. shouldn't work.
            // SR <= 5.3.4 returns Unauthorized with empty Content (HttpRequestException)
            // 5.3.4 < SR <= 5.3.8 returns Unauthorized with message but without error_code (SchemaRegistryException)
            // SR >= 5.40 returns Unauthorized with message and error_code (SchemaRegistryException)
            var schemaRegistryException = Assert.Throws <SchemaRegistryException>(() =>
            {
                var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                    Url = config.ServerWithAuth
                });
                var topicName = Guid.NewGuid().ToString();
                var subject   = SubjectNameStrategy.Topic.ConstructValueSubjectName(topicName, null);
                try
                {
                    var id = sr.RegisterSchemaAsync(subject, testSchema1).Result;
                }
                catch (Exception e)
                {
                    throw e.InnerException;
                }
            });

            Assert.Equal(401, schemaRegistryException.ErrorCode);
            Assert.Equal("Unauthorized; error code: 401", schemaRegistryException.Message);
        }
Ejemplo n.º 29
0
        public static void BasicAuth(Config config)
        {
            var testSchema1 =
                "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"Confluent.Kafka.Examples.AvroSpecific" +
                "\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"i" +
                "nt\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}";

            // 1. valid configuration cases

            // 1.1. credentials specified as USER_INFO.
            var conf = new Dictionary <string, string>
            {
                { "schema.registry.url", config.ServerWithAuth },
                { "schema.registry.basic.auth.credentials.source", "USER_INFO" },
                { "schema.registry.basic.auth.user.info", $"{config.Username}:{config.Password}" }
            };

            using (var sr = new CachedSchemaRegistryClient(conf))
            {
                var topicName = Guid.NewGuid().ToString();
                var subject   = sr.ConstructValueSubjectName(topicName);
                var id        = sr.RegisterSchemaAsync(subject, testSchema1).Result;
                var schema    = sr.GetLatestSchemaAsync(subject).Result;
                Assert.Equal(schema.Id, id);
            }

            // 1.2. credentials specified as USER_INFO implicitly (and using strongly typed SchemaRegistryConfig)
            var conf2 = new SchemaRegistryConfig
            {
                SchemaRegistryUrl = config.ServerWithAuth,
                SchemaRegistryBasicAuthUserInfo = $"{config.Username}:{config.Password}"
            };

            using (var sr = new CachedSchemaRegistryClient(conf2))
            {
                var topicName = Guid.NewGuid().ToString();
                var subject   = sr.ConstructValueSubjectName(topicName);
                var id        = sr.RegisterSchemaAsync(subject, testSchema1).Result;
                var schema    = sr.GetLatestSchemaAsync(subject).Result;
                Assert.Equal(schema.Id, id);
            }

            // 1.3. credentials specified as SASL_INHERIT.
            using (var sr = new CachedSchemaRegistryClient(
                       new Dictionary <string, string>
            {
                { "schema.registry.url", config.ServerWithAuth },
                { "schema.registry.basic.auth.credentials.source", "SASL_INHERIT" },
                { "sasl.username", config.Username },
                { "sasl.password", config.Password }
            }))
            {
                var topicName = Guid.NewGuid().ToString();
                var subject   = sr.ConstructValueSubjectName(topicName);
                var id        = sr.RegisterSchemaAsync(subject, testSchema1).Result;
                var schema    = sr.GetLatestSchemaAsync(subject).Result;
                Assert.Equal(schema.Id, id);
            }

            // 1.4. credentials specified as SASL_INHERIT via strongly typed config.
            var conf3 = new SchemaRegistryConfig {
                SchemaRegistryUrl = config.ServerWithAuth
            };

            conf3.Set(SchemaRegistryConfig.PropertyNames.SchemaRegistryBasicAuthCredentialsSource, "SASL_INHERIT");
            conf3.Set("sasl.username", config.Username);
            conf3.Set("sasl.password", config.Password);
            using (var sr = new CachedSchemaRegistryClient(conf3))
            {
                var topicName = Guid.NewGuid().ToString();
                var subject   = sr.ConstructValueSubjectName(topicName);
                var id        = sr.RegisterSchemaAsync(subject, testSchema1).Result;
                var schema    = sr.GetLatestSchemaAsync(subject).Result;
                Assert.Equal(schema.Id, id);
            }


            // 2. invalid configuration cases

            Assert.Throws <ArgumentException>(() =>
            {
                var sr = new CachedSchemaRegistryClient(new Dictionary <string, string>
                {
                    { "schema.registry.url", config.ServerWithAuth },
                    { "schema.registry.basic.auth.credentials.source", "SASL_INHERIT" },
                    { "schema.registry.basic.auth.user.info", $"{config.Username:config.Password}" }
                });
            });

            Assert.Throws <ArgumentException>(() =>
            {
                var sr = new CachedSchemaRegistryClient(new Dictionary <string, string>
                {
                    { "schema.registry.url", config.ServerWithAuth },
                    { "schema.registry.basic.auth.credentials.source", "USER_INFO" },
                    { "sasl.username", config.Username },
                    { "sasl.password", config.Password }
                });
            });

            // connect to authenticating without credentials. shouldn't work.
            Assert.Throws <HttpRequestException>(() =>
            {
                var sr = new CachedSchemaRegistryClient(new SchemaRegistryConfig {
                    SchemaRegistryUrl = config.ServerWithAuth
                });
                var topicName = Guid.NewGuid().ToString();
                var subject   = sr.ConstructValueSubjectName(topicName);
                try
                {
                    var id = sr.RegisterSchemaAsync(subject, testSchema1).Result;
                }
                catch (Exception e)
                {
                    throw e.InnerException;
                }
            });
        }