diff --git a/src/ApiGenerator/Configuration/CodeConfiguration.cs b/src/ApiGenerator/Configuration/CodeConfiguration.cs index 982af949aa7..c0f9ecfcb6d 100644 --- a/src/ApiGenerator/Configuration/CodeConfiguration.cs +++ b/src/ApiGenerator/Configuration/CodeConfiguration.cs @@ -62,7 +62,6 @@ public static class CodeConfiguration "cat.ml_datafeeds.json", "cat.ml_jobs.json", "cat.ml_trained_models.json", - "cat.transforms.json", "cluster.delete_component_template.json", "cluster.get_component_template.json", "cluster.put_component_template.json", diff --git a/src/Elasticsearch.Net/Api/RequestParameters/RequestParameters.Cat.cs b/src/Elasticsearch.Net/Api/RequestParameters/RequestParameters.Cat.cs index 46794b6c362..03b6f2342c7 100644 --- a/src/Elasticsearch.Net/Api/RequestParameters/RequestParameters.Cat.cs +++ b/src/Elasticsearch.Net/Api/RequestParameters/RequestParameters.Cat.cs @@ -1478,7 +1478,7 @@ public bool? Verbose } ///Request options for Transforms https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-transforms.html - public class TransformsRequestParameters : RequestParameters + public class CatTransformsRequestParameters : RequestParameters { public override HttpMethod DefaultHttpMethod => HttpMethod.GET; public override bool SupportsBody => false; diff --git a/src/Elasticsearch.Net/ElasticLowLevelClient.Cat.cs b/src/Elasticsearch.Net/ElasticLowLevelClient.Cat.cs index 29ac0afd1a0..8c4384f3478 100644 --- a/src/Elasticsearch.Net/ElasticLowLevelClient.Cat.cs +++ b/src/Elasticsearch.Net/ElasticLowLevelClient.Cat.cs @@ -432,23 +432,23 @@ public Task ThreadPoolAsync(string threadPoolPatterns, Cat where TResponse : class, IElasticsearchResponse, new() => DoRequestAsync(GET, Url($"_cat/thread_pool/{threadPoolPatterns:threadPoolPatterns}"), ctx, null, RequestParams(requestParameters)); ///GET on /_cat/transforms https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-transforms.html ///Request specific configuration such as querystring parameters & request specific connection settings. - public TResponse Transforms(TransformsRequestParameters requestParameters = null) + public TResponse Transforms(CatTransformsRequestParameters requestParameters = null) where TResponse : class, IElasticsearchResponse, new() => DoRequest(GET, "_cat/transforms", null, RequestParams(requestParameters)); ///GET on /_cat/transforms https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-transforms.html ///Request specific configuration such as querystring parameters & request specific connection settings. [MapsApi("cat.transforms", "")] - public Task TransformsAsync(TransformsRequestParameters requestParameters = null, CancellationToken ctx = default) + public Task TransformsAsync(CatTransformsRequestParameters requestParameters = null, CancellationToken ctx = default) where TResponse : class, IElasticsearchResponse, new() => DoRequestAsync(GET, "_cat/transforms", ctx, null, RequestParams(requestParameters)); ///GET on /_cat/transforms/{transform_id} https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-transforms.html ///The id of the transform for which to get stats. '_all' or '*' implies all transforms ///Request specific configuration such as querystring parameters & request specific connection settings. - public TResponse Transforms(string transformId, TransformsRequestParameters requestParameters = null) + public TResponse Transforms(string transformId, CatTransformsRequestParameters requestParameters = null) where TResponse : class, IElasticsearchResponse, new() => DoRequest(GET, Url($"_cat/transforms/{transformId:transformId}"), null, RequestParams(requestParameters)); ///GET on /_cat/transforms/{transform_id} https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-transforms.html ///The id of the transform for which to get stats. '_all' or '*' implies all transforms ///Request specific configuration such as querystring parameters & request specific connection settings. [MapsApi("cat.transforms", "transform_id")] - public Task TransformsAsync(string transformId, TransformsRequestParameters requestParameters = null, CancellationToken ctx = default) + public Task TransformsAsync(string transformId, CatTransformsRequestParameters requestParameters = null, CancellationToken ctx = default) where TResponse : class, IElasticsearchResponse, new() => DoRequestAsync(GET, Url($"_cat/transforms/{transformId:transformId}"), ctx, null, RequestParams(requestParameters)); } } \ No newline at end of file diff --git a/src/Nest/Cat/CatTransforms/CatTransformsRecord.cs b/src/Nest/Cat/CatTransforms/CatTransformsRecord.cs new file mode 100644 index 00000000000..b0ef9b54fa0 --- /dev/null +++ b/src/Nest/Cat/CatTransforms/CatTransformsRecord.cs @@ -0,0 +1,179 @@ +using System; +using System.Runtime.Serialization; +using Elasticsearch.Net.Utf8Json; + +namespace Nest +{ + [DataContract] + public class CatTransformsRecord : ICatRecord + { + /// + /// The timestamp when changes were last detected in the source indices. + /// + [DataMember(Name ="changes_last_detection_time")] + public string ChangesLastDetectionTime { get; internal set; } + + /// + /// Exponential moving average of the duration of the checkpoint, in milliseconds. + /// + [DataMember(Name ="checkpoint_duration_time_exp_avg")] + public long? CheckpointDurationTimeExpAvg { get; internal set; } + + /// + /// (Default) The time the transform was created. + /// + [DataMember(Name ="create_time")] + public DateTimeOffset CreateTime { get; internal set; } + + /// + /// (Default) The description of the transform. + /// + [DataMember(Name ="description")] + public string Description { get; internal set; } + + /// + /// (Default) The destination index for the transform. + /// + [DataMember(Name ="dest_index")] + public string DestinationIndex { get; internal set; } + + /// + /// The number of documents that have been indexed into the destination index for the transform. + /// + [DataMember(Name ="documents_indexed")] + public long? DocumentsIndexed { get; internal set; } + + /// + /// The number of documents that have been processed from the source index of the transform. + /// + [DataMember(Name ="documents_processed")] + public long? DocumentsProcessed { get; internal set; } + + /// + /// (Default) The interval between checks for changes in the source indices when the transform is running continuously. Also determines the + /// retry interval in the event of transient failures while the transform is searching or indexing. The minimum value is 1s and the maximum + /// is 1h. The default value is 1m. + /// + [DataMember(Name ="frequency")] + public Time Frequency { get; internal set; } + + /// + /// (Default) Identifier for the transform. This identifier can contain lowercase alphanumeric characters (a-z and 0-9), hyphens, and + /// underscores. It must start and end with alphanumeric characters. + /// + [DataMember(Name ="id")] + public string Id { get; internal set; } + + /// + /// The number of indexing failures. + /// + [DataMember(Name ="index_failure")] + public long? IndexFailure { get; internal set; } + + /// + /// The amount of time spent indexing, in milliseconds. + /// + [DataMember(Name ="index_time")] + public long? IndexTime { get; internal set; } + + /// + /// The number of indices created. + /// + [DataMember(Name ="index_total")] + public long? IndexTotal { get; internal set; } + + /// + /// Exponential moving average of the number of new documents that have been indexed. + /// + [DataMember(Name ="indexed_documents_exp_avg")] + public long? IndexedDocumentsExpAvg { get; internal set; } + + /// + /// (Default) Defines the initial page size to use for the composite aggregation for each checkpoint. If circuit breaker exceptions occur, + /// the page size is dynamically adjusted to a lower value. The minimum value is 10 and the maximum is 10,000. The default value is 500. + /// + [DataMember(Name ="max_page_search_size")] + public long? MaxPageSearchSize { get; internal set; } + + /// + /// The number of search or bulk index operations processed. Documents are processed in batches instead of individually. + /// + [DataMember(Name ="pages_processed")] + public long? PagesProcessed { get; internal set; } + + /// + /// (Default) The unique identifier for a pipeline. + /// + [DataMember(Name ="pipeline")] + public string Pipeline { get; internal set; } + + /// + /// Exponential moving average of the number of documents that have been processed. + /// + [DataMember(Name ="processed_documents_exp_avg")] + public long? ProcessedDocumentsExpAvg { get; internal set; } + + /// + /// The amount of time spent processing results, in milliseconds. + /// + [DataMember(Name ="processing_time")] + public long? ProcessingTime { get; internal set; } + + /// + /// If a transform has a failed state, this property provides details about the reason for the failure. + /// + [DataMember(Name ="reason")] + public string Reason { get; internal set; } + + /// + /// The number of search failures. + /// + [DataMember(Name ="search_failure")] + public long? SearchFailure { get; internal set; } + + /// + /// The amount of time spent searching, in milliseconds. + /// + [DataMember(Name ="search_time")] + public long? SearchTime { get; internal set; } + + /// + /// The number of search operations on the source index for the transform. + /// + [DataMember(Name ="search_total")] + public long? SearchTotal { get; internal set; } + + /// + /// (Default) The source indices for the transform. It can be a single index, an index pattern (for example, "myindex*"), an array of indices + /// (for example, ["index1", "index2"]), or an array of index patterns (for example, ["myindex1-*", "myindex2-*"]. + /// + [DataMember(Name ="source_index")] + [JsonFormatter(typeof(IndicesFormatter))] + public Indices SourceIndices { get; internal set; } + + /// + /// (Default) The status of the transform. + /// + [DataMember(Name ="state")] + public TransformState State { get; internal set; } + + /// + /// (Default) Indicates the type of transform. + /// + [DataMember(Name ="transform_type")] + public TransformType TransformType { get; internal set; } + + /// + /// The number of times the transform has been triggered by the scheduler. For example, the scheduler triggers the transform indexer to + /// check for updates or ingest new data at an interval specified in the frequency property. + /// + [DataMember(Name ="trigger_count")] + public long? TriggerCount { get; internal set; } + + /// + /// (Default) The version of Elasticsearch that existed on the node when the transform was created. + /// + [DataMember(Name ="version")] + public string Version { get; internal set; } + } +} diff --git a/src/Nest/Cat/CatTransforms/CatTransformsRequest.cs b/src/Nest/Cat/CatTransforms/CatTransformsRequest.cs new file mode 100644 index 00000000000..44a161ebf2c --- /dev/null +++ b/src/Nest/Cat/CatTransforms/CatTransformsRequest.cs @@ -0,0 +1,9 @@ +namespace Nest +{ + [MapsApi("cat.transforms.json")] + public partial interface ICatTransformsRequest { } + + public partial class CatTransformsRequest { } + + public partial class CatTransformsDescriptor { } +} diff --git a/src/Nest/Cat/CatTransforms/TransformState.cs b/src/Nest/Cat/CatTransforms/TransformState.cs new file mode 100644 index 00000000000..cbf203c3d1d --- /dev/null +++ b/src/Nest/Cat/CatTransforms/TransformState.cs @@ -0,0 +1,16 @@ +using System.Runtime.Serialization; +using Elasticsearch.Net; + +namespace Nest +{ + [StringEnum] + public enum TransformState + { + [EnumMember(Value = "STARTED")] Started, + [EnumMember(Value = "INDEXING")] Indexing, + [EnumMember(Value = "ABORTING")] Aborting, + [EnumMember(Value = "STOPPING")] Stopping, + [EnumMember(Value = "STOPPED")] Stopped, + [EnumMember(Value = "FAILED")] Failed + } +} diff --git a/src/Nest/Cat/CatTransforms/TransformType.cs b/src/Nest/Cat/CatTransforms/TransformType.cs new file mode 100644 index 00000000000..e9399f3a4fd --- /dev/null +++ b/src/Nest/Cat/CatTransforms/TransformType.cs @@ -0,0 +1,15 @@ +using System.Runtime.Serialization; +using Elasticsearch.Net; + +namespace Nest +{ + [StringEnum] + public enum TransformType + { + [EnumMember(Value = "batch")] + Batch, + + [EnumMember(Value = "continuous")] + Continuous + } +} diff --git a/src/Nest/Descriptors.Cat.cs b/src/Nest/Descriptors.Cat.cs index d6e312a6e9c..ba1429e911d 100644 --- a/src/Nest/Descriptors.Cat.cs +++ b/src/Nest/Descriptors.Cat.cs @@ -652,4 +652,42 @@ public CatThreadPoolDescriptor(Names threadPoolPatterns): base(r => r.Optional(" ///Verbose mode. Display column headers public CatThreadPoolDescriptor Verbose(bool? verbose = true) => Qs("v", verbose); } + + ///Descriptor for Transforms https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-transforms.html + public partial class CatTransformsDescriptor : RequestDescriptorBase, ICatTransformsRequest + { + internal override ApiUrls ApiUrls => ApiUrlsLookups.CatTransforms; + ////_cat/transforms + public CatTransformsDescriptor(): base() + { + } + + ////_cat/transforms/{transform_id} + ///Optional, accepts null + public CatTransformsDescriptor(Id transformId): base(r => r.Optional("transform_id", transformId)) + { + } + + // values part of the url path + Id ICatTransformsRequest.TransformId => Self.RouteValues.Get("transform_id"); + ///The id of the transform for which to get stats. '_all' or '*' implies all transforms + public CatTransformsDescriptor TransformId(Id transformId) => Assign(transformId, (a, v) => a.RouteValues.Optional("transform_id", v)); + // Request parameters + ///Whether to ignore if a wildcard expression matches no transforms. (This includes `_all` string or when no transforms have been specified) + public CatTransformsDescriptor AllowNoMatch(bool? allownomatch = true) => Qs("allow_no_match", allownomatch); + ///a short version of the Accept header, e.g. json, yaml + public CatTransformsDescriptor Format(string format) => Qs("format", format); + ///skips a number of transform configs, defaults to 0 + public CatTransformsDescriptor From(int? from) => Qs("from", from); + ///Comma-separated list of column names to display + public CatTransformsDescriptor Headers(params string[] headers) => Qs("h", headers); + ///Return help information + public CatTransformsDescriptor Help(bool? help = true) => Qs("help", help); + ///specifies a max number of transforms to get, defaults to 100 + public CatTransformsDescriptor Size(int? size) => Qs("size", size); + ///Comma-separated list of column names or column aliases to sort by + public CatTransformsDescriptor SortByColumns(params string[] sortbycolumns) => Qs("s", sortbycolumns); + ///Verbose mode. Display column headers + public CatTransformsDescriptor Verbose(bool? verbose = true) => Qs("v", verbose); + } } \ No newline at end of file diff --git a/src/Nest/ElasticClient.Cat.cs b/src/Nest/ElasticClient.Cat.cs index 7b5378d1748..e2bf21a3678 100644 --- a/src/Nest/ElasticClient.Cat.cs +++ b/src/Nest/ElasticClient.Cat.cs @@ -516,5 +516,29 @@ internal CatNamespace(ElasticClient client): base(client) /// https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-thread-pool.html /// public Task> ThreadPoolAsync(ICatThreadPoolRequest request, CancellationToken ct = default) => DoCatAsync(request, ct); + /// + /// GET request to the cat.transforms API, read more about this API online: + /// + /// https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-transforms.html + /// + public CatResponse Transforms(Func selector = null) => Transforms(selector.InvokeOrDefault(new CatTransformsDescriptor())); + /// + /// GET request to the cat.transforms API, read more about this API online: + /// + /// https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-transforms.html + /// + public Task> TransformsAsync(Func selector = null, CancellationToken ct = default) => TransformsAsync(selector.InvokeOrDefault(new CatTransformsDescriptor()), ct); + /// + /// GET request to the cat.transforms API, read more about this API online: + /// + /// https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-transforms.html + /// + public CatResponse Transforms(ICatTransformsRequest request) => DoCat(request); + /// + /// GET request to the cat.transforms API, read more about this API online: + /// + /// https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-transforms.html + /// + public Task> TransformsAsync(ICatTransformsRequest request, CancellationToken ct = default) => DoCatAsync(request, ct); } } \ No newline at end of file diff --git a/src/Nest/Requests.Cat.cs b/src/Nest/Requests.Cat.cs index e072d2b1fd9..969781d952a 100644 --- a/src/Nest/Requests.Cat.cs +++ b/src/Nest/Requests.Cat.cs @@ -1554,4 +1554,95 @@ public bool? Verbose set => Q("v", value); } } + + [InterfaceDataContract] + public partial interface ICatTransformsRequest : IRequest + { + [IgnoreDataMember] + Id TransformId + { + get; + } + } + + ///Request for Transforms https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-transforms.html + public partial class CatTransformsRequest : PlainRequestBase, ICatTransformsRequest + { + protected ICatTransformsRequest Self => this; + internal override ApiUrls ApiUrls => ApiUrlsLookups.CatTransforms; + ////_cat/transforms + public CatTransformsRequest(): base() + { + } + + ////_cat/transforms/{transform_id} + ///Optional, accepts null + public CatTransformsRequest(Id transformId): base(r => r.Optional("transform_id", transformId)) + { + } + + // values part of the url path + [IgnoreDataMember] + Id ICatTransformsRequest.TransformId => Self.RouteValues.Get("transform_id"); + // Request parameters + ///Whether to ignore if a wildcard expression matches no transforms. (This includes `_all` string or when no transforms have been specified) + public bool? AllowNoMatch + { + get => Q("allow_no_match"); + set => Q("allow_no_match", value); + } + + ///a short version of the Accept header, e.g. json, yaml + public string Format + { + get => Q("format"); + set + { + Q("format", value); + SetAcceptHeader(value); + } + } + + ///skips a number of transform configs, defaults to 0 + public int? From + { + get => Q("from"); + set => Q("from", value); + } + + ///Comma-separated list of column names to display + public string[] Headers + { + get => Q("h"); + set => Q("h", value); + } + + ///Return help information + public bool? Help + { + get => Q("help"); + set => Q("help", value); + } + + ///specifies a max number of transforms to get, defaults to 100 + public int? Size + { + get => Q("size"); + set => Q("size", value); + } + + ///Comma-separated list of column names or column aliases to sort by + public string[] SortByColumns + { + get => Q("s"); + set => Q("s", value); + } + + ///Verbose mode. Display column headers + public bool? Verbose + { + get => Q("v"); + set => Q("v", value); + } + } } \ No newline at end of file diff --git a/tests/Tests/Cat/CatTransform/CatTransformsApiTests.cs b/tests/Tests/Cat/CatTransform/CatTransformsApiTests.cs new file mode 100644 index 00000000000..54b357fc8ed --- /dev/null +++ b/tests/Tests/Cat/CatTransform/CatTransformsApiTests.cs @@ -0,0 +1,59 @@ +using System; +using Elasticsearch.Net; +using Nest; +using Tests.Core.Extensions; +using Tests.Core.ManagedElasticsearch.Clusters; +using Tests.Framework.EndpointTests; +using Tests.Framework.EndpointTests.TestState; +using Elastic.Xunit.XunitPlumbing; + +namespace Tests.Cat.CatTransforms +{ + [SkipVersion("<7.5.0", "Introduced in 7.5.0")] + public class CatTransformsApiTests + : ApiIntegrationTestBase, ICatTransformsRequest, CatTransformsDescriptor, CatTransformsRequest> + { + public CatTransformsApiTests(ReadOnlyCluster cluster, EndpointUsage usage) : base(cluster, usage) { } + + protected override bool ExpectIsValid => true; + protected override int ExpectStatusCode => 200; + protected override HttpMethod HttpMethod => HttpMethod.GET; + protected override string UrlPath => "/_cat/transforms"; + + protected override LazyResponses ClientUsage() => Calls( + (client, f) => client.Cat.Transforms(f), + (client, f) => client.Cat.TransformsAsync(f), + (client, r) => client.Cat.Transforms(r), + (client, r) => client.Cat.TransformsAsync(r) + ); + + protected override void ExpectResponse(CatResponse response) => response.ShouldBeValid(); + } + + [SkipVersion("<7.5.0", "Introduced in 7.5.0")] + public class CatTransformsFullApiTests + : ApiIntegrationTestBase, ICatTransformsRequest, CatTransformsDescriptor, + CatTransformsRequest> + { + public CatTransformsFullApiTests(ReadOnlyCluster cluster, EndpointUsage usage) : base(cluster, usage) { } + + protected override bool ExpectIsValid => true; + protected override int ExpectStatusCode => 200; + + protected override Func Fluent => f => f; + protected override HttpMethod HttpMethod => HttpMethod.GET; + + protected override CatTransformsRequest Initializer { get; } = new CatTransformsRequest { }; + + protected override string UrlPath => "/_cat/transforms"; + + protected override LazyResponses ClientUsage() => Calls( + (client, f) => client.Cat.Transforms(f), + (client, f) => client.Cat.TransformsAsync(f), + (client, r) => client.Cat.Transforms(r), + (client, r) => client.Cat.TransformsAsync(r) + ); + + protected override void ExpectResponse(CatResponse response) => response.ShouldBeValid(); + } +} diff --git a/tests/Tests/Cat/CatTransform/CatTransformsUrlTests.cs b/tests/Tests/Cat/CatTransform/CatTransformsUrlTests.cs new file mode 100644 index 00000000000..d3edd25514f --- /dev/null +++ b/tests/Tests/Cat/CatTransform/CatTransformsUrlTests.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using Elastic.Xunit.XunitPlumbing; +using Nest; +using Tests.Framework.EndpointTests; +using static Tests.Framework.EndpointTests.UrlTester; + +namespace Tests.Cat.CatTransforms +{ + public class CatTransformsUrlTests : UrlTestsBase + { + [U] public override async Task Urls() + { + await GET("/_cat/transforms") + .Fluent(c => c.Cat.Transforms()) + .Request(c => c.Cat.Transforms(new CatTransformsRequest())) + .FluentAsync(c => c.Cat.TransformsAsync()) + .RequestAsync(c => c.Cat.TransformsAsync(new CatTransformsRequest())); + + await GET("/_cat/transforms/transform-id") + .Fluent(c => c.Cat.Transforms(f => f.TransformId("transform-id"))) + .Request(c => c.Cat.Transforms(new CatTransformsRequest("transform-id"))) + .FluentAsync(c => c.Cat.TransformsAsync(f => f.TransformId("transform-id"))) + .RequestAsync(c => c.Cat.TransformsAsync(new CatTransformsRequest("transform-id"))); + } + } +}