Skip to content

Commit

Permalink
Add parent-child relationships to documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
russcam committed Jan 10, 2018
1 parent 1ad5adf commit a55e258
Show file tree
Hide file tree
Showing 12 changed files with 622 additions and 249 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,11 @@ foreach (var bucket in projects.Buckets)
}
----

[source,csharp]
----
response.ShouldBeValid();
var centroid = response.Aggregations.GeoCentroid("centroid");
centroid.Should().NotBeNull();
centroid.Count.Should().Be(0);
----

Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public class AllowAllCertificatesCluster : SslAndKpiXPackCluster
If your client application has access to the public CA certificate locally, Elasticsearch.NET and NEST ship with some handy helpers
that can assert that a certificate the server presents is one that came from the local CA.

If you use X-Pack's `certgen` tool to {xpack_current}/ssl-tls.html[generate SSL certificates], the generated node certificate
If you use X-Pack's {ref_current}/certutil.html`certutil` tool] to generate SSL certificates, the generated node certificate
does not include the CA in the certificate chain, in order to cut down on SSL handshake size. In those case you can use`CertificateValidations.AuthorityIsRoot` and pass it your local copy of the CA public key to assert that
the certificate the server presented was generated using it

Expand Down Expand Up @@ -115,16 +115,16 @@ the local CA certificate is part of the chain that was used to generate the serv
==== Client Certificates

X-Pack also allows you to configure a {xpack_current}/pki-realm.html[PKI realm] to enable user authentication
through client certificates. The `certgen` tool included with X-Pack allows you to
{ref_current}/certgen.html[generate client certificates as well] and assign the distinguished name (DN) of the
through client certificates. The {ref_current}/certutil.html`certutil` tool] included with X-Pack allows you to
generate client certificates as well and assign the distinguished name (DN) of the
certificate to a user with a certain role.

certgen by default only generates a public certificate `.cer`) and a private key `.key`. To authenticate with client certificates, you need to present both
By default, the `certutil` tool only generates a public certificate `.cer`) and a private key `.key`. To authenticate with client certificates, you need to present both
as one certificate. The easiest way to do this is to generate a `pfx` or `p12` file from the `.cer` and `.key`
and attach these to requests using `new X509Certificate(pathToPfx)`.

If you do not have a way to run `openssl` or `Pvk2Pfx` to do this as part of your deployments the clients ships with a handy helper to generate one
on the fly by passing the paths to the `.cer` and `.key` files that `certgen` outputs. Sadly, this functonality is not available on .NET Core because
on the fly by passing the paths to the `.cer` and `.key` files that `certutil` outputs. Sadly, this functonality is not available on .NET Core because
the `PublicKey` property cannot be set on the crypto service provider that is used to generate the `pfx` file at runtime.

You can set Client Certificates to use on all connections on `ConnectionSettings`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,19 +175,29 @@ var audit = new Auditor(() => Framework.Cluster
.Settings(s => s.SniffOnStartup(false))
);
Action<Audit, string, int> hostAssert = (a, host, expectedPort) =>
void HostAssert(Audit a, string host, int expectedPort)
{
a.Node.Uri.Host.Should().Be(host);
a.Node.Uri.Port.Should().Be(expectedPort);
};
}
void SniffUrlAssert(Audit a, string host, int expectedPort)
{
HostAssert(a, host, expectedPort);
var sniffUri = new UriBuilder(a.Node.Uri)
{
Path = RequestPipeline.SniffPath,
Query = "?flat_settings=true&timeout=2s"
}.Uri;
sniffUri.PathEquals(a.Path, nameof(SniffUrlAssert));
}
audit = await audit.TraceCalls(
new ClientCall {
{ PingFailure, a => hostAssert(a, "localhost", 9200)},
{ PingFailure, a => HostAssert(a, "localhost", 9200)},
{ SniffOnFail },
{ SniffSuccess, a => hostAssert(a, "localhost", 9200)},
{ PingSuccess, a => hostAssert(a, "10.0.12.1", 9200)},
{ HealthyResponse, a => hostAssert(a, "10.0.12.1", 9200)},
{ SniffSuccess, a => SniffUrlAssert(a, "localhost", 9200)},
{ PingSuccess, a => HostAssert(a, "10.0.12.1", 9200)},
{ HealthyResponse, a => HostAssert(a, "10.0.12.1", 9200)},
{ pool => pool.Nodes.Count.Should().Be(10) } <1>
}
);
Expand Down
192 changes: 192 additions & 0 deletions docs/client-concepts/high-level/inference/routing-inference.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/master

:github: https://github.com/elastic/elasticsearch-net

:nuget: https://www.nuget.org/packages

////
IMPORTANT NOTE
==============
This file has been generated from https://github.com/elastic/elasticsearch-net/tree/master/src/Tests/ClientConcepts/HighLevel/Inference/RoutingInference.doc.cs.
If you wish to submit a PR for any spelling mistakes, typos or grammatical errors for this file,
please modify the original csharp file found at the link and submit the PR with that change. Thanks!
////

[[routing-inference]]
=== Routing inference

==== Implicit conversion

You can always create a routing explicitly by relying on the implicit conversion from the following types

* `Int32`

* `Int64`

* `String`

* `Guid`

Methods and Properties that take an `Routing` can be passed any of these types and it will be implicitly
converted to an instance of `Routing`

[source,csharp]
----
Routing routingFromInt = 1;
Routing routingFromLong = 2L;
Routing routingFromString = "hello-world";
Routing routingFromGuid = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E");
Expect(1).WhenSerializing(routingFromInt);
Expect(2).WhenSerializing(routingFromLong);
Expect("hello-world").WhenSerializing(routingFromString);
Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenSerializing(routingFromGuid);
----

==== Inferring from a type

The real power of the `Routing` is in the inference rules (the default inferred routing for an object will be null).
Lets look at an example of this given the following POCO:

[source,csharp]
----
class MyDTO
{
public Guid Routing { get; set; }
public string Name { get; set; }
public string OtherName { get; set; }
}
----

By default NEST will try to find a property called `Routing` on the class using reflection
and create a cached delegate based on the property getter

[source,csharp]
----
var dto = new MyDTO
{
Routing = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"),
Name = "x",
OtherName = "y"
};
Expect(null).WhenInferringRoutingOn(dto);
----

Using connection settings, you can specify a property that NEST should use to infer Routing for the document.
Here we instruct NEST to infer the Routing for `MyDTO` based on its `Name` property

[source,csharp]
----
WithConnectionSettings(x => x
.InferMappingFor<MyDTO>(m => m
.RoutingProperty(p => p.Name)
)
).Expect("x").WhenInferringRoutingOn(dto);
----

IMPORTANT: Inference rules are cached __per__ `ConnectionSettings` instance.

Because the cache is per `ConnectionSettings` instance, we can create another `ConnectionSettings` instance
with different inference rules

[source,csharp]
----
WithConnectionSettings(x => x
.InferMappingFor<MyDTO>(m => m
.RoutingProperty(p => p.OtherName)
)
).Expect("y").WhenInferringRoutingOn(dto);
----

==== JoinField

If your class has a property of type JoinField, NEST will automatically infer the parentid as the routing value.

The name of this property can be anything. Be sure the read the <<parent-child-relationships, section on Parent/Child relationships>> to get a complete
walkthrough on using Parent Child joins with NEST.

[source,csharp]
----
class MyOtherDTO
{
public JoinField SomeJoinField { get; set; }
public Guid Id { get; set; }
public string Name { get; set; }
public string OtherName { get; set; }
}
----

here we link this instance of `MyOtherDTO` with its parent id `"8080"`

[source,csharp]
----
var dto = new MyOtherDTO
{
SomeJoinField = JoinField.Link<MyOtherDTO>("8080"),
Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"),
Name = "x",
OtherName = "y"
};
Expect("8080").WhenInferringRoutingOn(dto);
----

Here we link this instance as the root (parent) of the relation. NEST infers that the default routing for this instance
should be the Id of the document itself.

[source,csharp]
----
dto = new MyOtherDTO
{
SomeJoinField = JoinField.Root<MyOtherDTO>(),
Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"),
Name = "x",
OtherName = "y"
};
Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenInferringRoutingOn(dto);
----

==== Precedence of ConnectionSettings

The routing property configured on `ConnectionSettings` always takes precedence.

[source,csharp]
----
WithConnectionSettings(x => x
.InferMappingFor<MyOtherDTO>(m => m
.RoutingProperty(p => p.OtherName)
)
).Expect("y").WhenInferringRoutingOn(dto);
class BadDTO
{
public JoinField SomeJoinField { get; set; }
public JoinField AnotherJoinField { get; set; }
public string ParentName { get; set; }
}
----

A class cannot contain more than one property of type JoinField, an exception is thrown in this case

[source,csharp]
----
var dto = new BadDTO
{
SomeJoinField = JoinField.Link<MyOtherDTO>("8080"),
AnotherJoinField = JoinField.Link<MyOtherDTO>("8081"),
ParentName = "my-parent"
};
Action resolve = () => Expect("8080").WhenInferringRoutingOn(dto);
resolve.ShouldThrow<ArgumentException>().WithMessage("BadDTO has more than one JoinField property");
----

unless you configure the ConnectionSettings to use an alternate property:

[source,csharp]
----
WithConnectionSettings(x => x
.InferMappingFor<BadDTO>(m => m
.RoutingProperty(p => p.ParentName)
)
).Expect("my-parent").WhenInferringRoutingOn(dto);
----

Loading

0 comments on commit a55e258

Please sign in to comment.