From a7629d9b7d1043e670ca51d09f89a65fb1c88680 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Wed, 25 Apr 2018 08:52:03 -0600 Subject: [PATCH 1/3] Require acknowledgement to start_trial license This is related to #30134. It modifies the start_trial action to require an acknowledgement parameter in the rest request to actually start the trial license. There are backwards compatibility issues as prior ES versions did not support this parameter. To handle this, it is assumed that a request coming from a node prior to 6.3 is acknowledged. And attempts to write a non-acknowledged request to a prior to 6.3 node will throw an exception. Additionally this PR adds messages about the trial license the user is generating. --- x-pack/docs/build.gradle | 1 - x-pack/docs/build.gradle.orig | 687 ++++++++++++++++++ .../en/rest-api/license/start-trial.asciidoc | 25 +- .../license/LicensingClient.java | 4 +- .../license/LicensingClient.java.orig | 67 ++ .../license/PostStartTrialRequest.java | 31 +- .../license/PostStartTrialRequest.java.orig | 55 ++ .../license/PostStartTrialRequestBuilder.java | 5 + .../PostStartTrialRequestBuilder.java.orig | 17 + .../license/PostStartTrialResponse.java | 72 +- .../license/PostStartTrialResponse.java.orig | 66 ++ .../license/RestGetTrialStatus.java | 2 +- .../license/RestGetTrialStatus.java.orig | 48 ++ .../license/RestPostStartTrialLicense.java | 30 +- .../RestPostStartTrialLicense.java.orig | 59 ++ .../license/StartTrialClusterTask.java | 22 +- .../license/StartTrialClusterTask.java.orig | 79 ++ .../license/StartTrialLicenseTests.java | 44 +- .../license/StartTrialLicenseTests.java.orig | 113 +++ .../api/xpack.license.post_start_trial.json | 4 + .../test/license/20_put_license.yml | 4 +- 21 files changed, 1396 insertions(+), 39 deletions(-) create mode 100644 x-pack/docs/build.gradle.orig create mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicensingClient.java.orig create mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequest.java.orig create mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequestBuilder.java.orig create mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java.orig create mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestGetTrialStatus.java.orig create mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestPostStartTrialLicense.java.orig create mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartTrialClusterTask.java.orig create mode 100644 x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartTrialLicenseTests.java.orig diff --git a/x-pack/docs/build.gradle b/x-pack/docs/build.gradle index ae851732daac8..ab9bc99459968 100644 --- a/x-pack/docs/build.gradle +++ b/x-pack/docs/build.gradle @@ -61,7 +61,6 @@ buildRestTests.expectedUnconvertedCandidates = [ 'en/watcher/trigger/schedule/yearly.asciidoc', 'en/watcher/troubleshooting.asciidoc', 'en/rest-api/license/delete-license.asciidoc', - 'en/rest-api/license/start-trial.asciidoc', 'en/rest-api/license/update-license.asciidoc', 'en/ml/api-quickref.asciidoc', 'en/rest-api/ml/delete-calendar-event.asciidoc', diff --git a/x-pack/docs/build.gradle.orig b/x-pack/docs/build.gradle.orig new file mode 100644 index 0000000000000..ae851732daac8 --- /dev/null +++ b/x-pack/docs/build.gradle.orig @@ -0,0 +1,687 @@ +import org.elasticsearch.gradle.test.NodeInfo + +import java.nio.charset.StandardCharsets + +apply plugin: 'elasticsearch.docs-test' + +/* List of files that have snippets that probably should be converted to + * `// CONSOLE` and `// TESTRESPONSE` but have yet to be converted. Try and + * only remove entries from this list. When it is empty we'll remove it + * entirely and have a party! There will be cake and everything.... */ +buildRestTests.expectedUnconvertedCandidates = [ + 'en/ml/functions/count.asciidoc', + 'en/ml/functions/geo.asciidoc', + 'en/ml/functions/info.asciidoc', + 'en/ml/functions/metric.asciidoc', + 'en/ml/functions/rare.asciidoc', + 'en/ml/functions/sum.asciidoc', + 'en/ml/functions/time.asciidoc', + 'en/ml/aggregations.asciidoc', + 'en/ml/customurl.asciidoc', + 'en/monitoring/indices.asciidoc', + 'en/rest-api/security/ssl.asciidoc', + 'en/rest-api/security/users.asciidoc', + 'en/rest-api/security/tokens.asciidoc', + 'en/rest-api/watcher/put-watch.asciidoc', + 'en/security/authentication/user-cache.asciidoc', + 'en/security/authorization/field-and-document-access-control.asciidoc', + 'en/security/authorization/run-as-privilege.asciidoc', + 'en/security/ccs-clients-integrations/http.asciidoc', + 'en/security/authorization/custom-roles-provider.asciidoc', + 'en/watcher/actions/email.asciidoc', + 'en/watcher/actions/hipchat.asciidoc', + 'en/watcher/actions/index.asciidoc', + 'en/watcher/actions/logging.asciidoc', + 'en/watcher/actions/pagerduty.asciidoc', + 'en/watcher/actions/slack.asciidoc', + 'en/watcher/actions/jira.asciidoc', + 'en/watcher/actions/webhook.asciidoc', + 'en/watcher/condition/always.asciidoc', + 'en/watcher/condition/array-compare.asciidoc', + 'en/watcher/condition/compare.asciidoc', + 'en/watcher/condition/never.asciidoc', + 'en/watcher/condition/script.asciidoc', + 'en/watcher/customizing-watches.asciidoc', + 'en/watcher/example-watches/example-watch-meetupdata.asciidoc', + 'en/watcher/how-watcher-works.asciidoc', + 'en/watcher/input/chain.asciidoc', + 'en/watcher/input/http.asciidoc', + 'en/watcher/input/search.asciidoc', + 'en/watcher/input/simple.asciidoc', + 'en/watcher/transform.asciidoc', + 'en/watcher/transform/chain.asciidoc', + 'en/watcher/transform/script.asciidoc', + 'en/watcher/transform/search.asciidoc', + 'en/watcher/trigger/schedule/cron.asciidoc', + 'en/watcher/trigger/schedule/daily.asciidoc', + 'en/watcher/trigger/schedule/hourly.asciidoc', + 'en/watcher/trigger/schedule/interval.asciidoc', + 'en/watcher/trigger/schedule/monthly.asciidoc', + 'en/watcher/trigger/schedule/weekly.asciidoc', + 'en/watcher/trigger/schedule/yearly.asciidoc', + 'en/watcher/troubleshooting.asciidoc', + 'en/rest-api/license/delete-license.asciidoc', + 'en/rest-api/license/start-trial.asciidoc', + 'en/rest-api/license/update-license.asciidoc', + 'en/ml/api-quickref.asciidoc', + 'en/rest-api/ml/delete-calendar-event.asciidoc', + 'en/rest-api/ml/delete-snapshot.asciidoc', + 'en/rest-api/ml/forecast.asciidoc', + 'en/rest-api/ml/get-bucket.asciidoc', + 'en/rest-api/ml/get-job-stats.asciidoc', + 'en/rest-api/ml/get-overall-buckets.asciidoc', + 'en/rest-api/ml/get-category.asciidoc', + 'en/rest-api/ml/get-record.asciidoc', + 'en/rest-api/ml/get-influencer.asciidoc', + 'en/rest-api/ml/get-snapshot.asciidoc', + 'en/rest-api/ml/post-data.asciidoc', + 'en/rest-api/ml/preview-datafeed.asciidoc', + 'en/rest-api/ml/revert-snapshot.asciidoc', + 'en/rest-api/ml/update-snapshot.asciidoc', + 'en/rest-api/ml/validate-detector.asciidoc', + 'en/rest-api/ml/validate-job.asciidoc', + 'en/rest-api/security/authenticate.asciidoc', + 'en/rest-api/watcher/stats.asciidoc', + 'en/security/authorization.asciidoc', + 'en/watcher/example-watches/watching-time-series-data.asciidoc', +] + +dependencies { + testCompile project(path: xpackModule('core'), configuration: 'runtime') + testCompile project(path: xpackModule('core'), configuration: 'testArtifacts') + testCompile project(path: xpackProject('plugin').path, configuration: 'testArtifacts') +} + +Closure waitWithAuth = { NodeInfo node, AntBuilder ant -> + File tmpFile = new File(node.cwd, 'wait.success') + // wait up to twenty seconds + final long stopTime = System.currentTimeMillis() + 20000L; + Exception lastException = null; + while (System.currentTimeMillis() < stopTime) { + lastException = null; + // we use custom wait logic here as the elastic user is not available immediately and ant.get will fail when a 401 is returned + HttpURLConnection httpURLConnection = null; + try { + httpURLConnection = (HttpURLConnection) new URL("http://${node.httpUri()}/_cluster/health").openConnection(); + httpURLConnection.setRequestProperty("Authorization", "Basic " + + Base64.getEncoder().encodeToString("test_admin:x-pack-test-password".getBytes(StandardCharsets.UTF_8))); + httpURLConnection.setRequestMethod("GET"); + httpURLConnection.setConnectTimeout(1000); + httpURLConnection.setReadTimeout(30000); + httpURLConnection.connect(); + if (httpURLConnection.getResponseCode() == 200) { + tmpFile.withWriter StandardCharsets.UTF_8.name(), { + it.write(httpURLConnection.getInputStream().getText(StandardCharsets.UTF_8.name())) + } + break; + } + } catch (Exception e) { + logger.debug("failed to call cluster health", e) + lastException = e + } finally { + if (httpURLConnection != null) { + httpURLConnection.disconnect(); + } + } + + // did not start, so wait a bit before trying again + Thread.sleep(500L); + } + if (tmpFile.exists() == false && lastException != null) { + logger.error("final attempt of calling cluster health failed", lastException) + } + return tmpFile.exists() +} + +// copy xpack rest api +File xpackResources = new File(xpackProject('plugin').projectDir, 'src/test/resources') +project.copyRestSpec.from(xpackResources) { + include 'rest-api-spec/api/**' +} +integTestCluster { + setting 'xpack.security.enabled', 'true' + setting 'xpack.security.authc.token.enabled', 'true' + // Disable monitoring exporters for the docs tests + setting 'xpack.monitoring.exporters._local.type', 'local' + setting 'xpack.monitoring.exporters._local.enabled', 'false' + setting 'xpack.license.self_generated.type', 'trial' + setupCommand 'setupTestAdmin', + 'bin/elasticsearch-users', 'useradd', 'test_admin', '-p', 'x-pack-test-password', '-r', 'superuser' + waitCondition = waitWithAuth +} + + + +buildRestTests.docs = fileTree(projectDir) { + // No snippets in here! + exclude 'build.gradle' + // That is where the snippets go, not where they come from! + exclude 'build' + // These file simply doesn't pass yet. We should figure out how to fix them. + exclude 'en/watcher/reference/actions.asciidoc' + exclude 'en/rest-api/graph/explore.asciidoc' +} + +Map setups = buildRestTests.setups +setups['my_inactive_watch'] = ''' + - do: + xpack.watcher.put_watch: + id: "my_watch" + active: false + body: > + { + "trigger": { + "schedule": { + "hourly": { + "minute": [ 0, 5 ] + } + } + }, + "input": { + "simple": { + "payload": { + "send": "yes" + } + } + }, + "condition": { + "always": {} + }, + "actions": { + "test_index": { + "index": { + "index": "test", + "doc_type": "test2" + } + } + } + } + - match: { _id: "my_watch" } +''' +setups['my_active_watch'] = setups['my_inactive_watch'].replace( + 'active: false', 'active: true') + +// Used by SQL because it looks SQL-ish +setups['library'] = ''' + - do: + indices.create: + index: library + body: + settings: + number_of_shards: 1 + number_of_replicas: 1 + mappings: + book: + properties: + name: + type: text + fields: + keyword: + type: keyword + author: + type: text + fields: + keyword: + type: keyword + release_date: + type: date + page_count: + type: short + - do: + bulk: + index: library + type: book + refresh: true + body: | + {"index":{"_id": "Leviathan Wakes"}} + {"name": "Leviathan Wakes", "author": "James S.A. Corey", "release_date": "2011-06-02", "page_count": 561} + {"index":{"_id": "Hyperion"}} + {"name": "Hyperion", "author": "Dan Simmons", "release_date": "1989-05-26", "page_count": 482} + {"index":{"_id": "Dune"}} + {"name": "Dune", "author": "Frank Herbert", "release_date": "1965-06-01", "page_count": 604} + {"index":{"_id": "Dune Messiah"}} + {"name": "Dune Messiah", "author": "Frank Herbert", "release_date": "1969-10-15", "page_count": 331} + {"index":{"_id": "Children of Dune"}} + {"name": "Children of Dune", "author": "Frank Herbert", "release_date": "1976-04-21", "page_count": 408} + {"index":{"_id": "God Emperor of Dune"}} + {"name": "God Emperor of Dune", "author": "Frank Herbert", "release_date": "1981-05-28", "page_count": 454} + {"index":{"_id": "Consider Phlebas"}} + {"name": "Consider Phlebas", "author": "Iain M. Banks", "release_date": "1987-04-23", "page_count": 471} + {"index":{"_id": "Pandora's Star"}} + {"name": "Pandora's Star", "author": "Peter F. Hamilton", "release_date": "2004-03-02", "page_count": 768} + {"index":{"_id": "Revelation Space"}} + {"name": "Revelation Space", "author": "Alastair Reynolds", "release_date": "2000-03-15", "page_count": 585} + {"index":{"_id": "A Fire Upon the Deep"}} + {"name": "A Fire Upon the Deep", "author": "Vernor Vinge", "release_date": "1992-06-01", "page_count": 613} + {"index":{"_id": "Ender's Game"}} + {"name": "Ender's Game", "author": "Orson Scott Card", "release_date": "1985-06-01", "page_count": 324} + {"index":{"_id": "1984"}} + {"name": "1984", "author": "George Orwell", "release_date": "1985-06-01", "page_count": 328} + {"index":{"_id": "Fahrenheit 451"}} + {"name": "Fahrenheit 451", "author": "Ray Bradbury", "release_date": "1953-10-15", "page_count": 227} + {"index":{"_id": "Brave New World"}} + {"name": "Brave New World", "author": "Aldous Huxley", "release_date": "1932-06-01", "page_count": 268} + {"index":{"_id": "Foundation"}} + {"name": "Foundation", "author": "Isaac Asimov", "release_date": "1951-06-01", "page_count": 224} + {"index":{"_id": "The Giver"}} + {"name": "The Giver", "author": "Lois Lowry", "release_date": "1993-04-26", "page_count": 208} + {"index":{"_id": "Slaughterhouse-Five"}} + {"name": "Slaughterhouse-Five", "author": "Kurt Vonnegut", "release_date": "1969-06-01", "page_count": 275} + {"index":{"_id": "The Hitchhiker's Guide to the Galaxy"}} + {"name": "The Hitchhiker's Guide to the Galaxy", "author": "Douglas Adams", "release_date": "1979-10-12", "page_count": 180} + {"index":{"_id": "Snow Crash"}} + {"name": "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "page_count": 470} + {"index":{"_id": "Neuromancer"}} + {"name": "Neuromancer", "author": "William Gibson", "release_date": "1984-07-01", "page_count": 271} + {"index":{"_id": "The Handmaid's Tale"}} + {"name": "The Handmaid's Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311} + {"index":{"_id": "Starship Troopers"}} + {"name": "Starship Troopers", "author": "Robert A. Heinlein", "release_date": "1959-12-01", "page_count": 335} + {"index":{"_id": "The Left Hand of Darkness"}} + {"name": "The Left Hand of Darkness", "author": "Ursula K. Le Guin", "release_date": "1969-06-01", "page_count": 304} + {"index":{"_id": "The Moon is a Harsh Mistress"}} + {"name": "The Moon is a Harsh Mistress", "author": "Robert A. Heinlein", "release_date": "1966-04-01", "page_count": 288} + +''' +setups['server_metrics_index'] = ''' + - do: + indices.create: + index: server-metrics + body: + settings: + number_of_shards: 1 + number_of_replicas: 0 + mappings: + metric: + properties: + timestamp: + type: date + total: + type: long +''' +setups['server_metrics_data'] = setups['server_metrics_index'] + ''' + - do: + bulk: + index: server-metrics + type: metric + refresh: true + body: | + {"index": {"_id":"1177"}} + {"timestamp":"2017-03-23T13:00:00","total":40476} + {"index": {"_id":"1178"}} + {"timestamp":"2017-03-23T13:00:00","total":15287} + {"index": {"_id":"1179"}} + {"timestamp":"2017-03-23T13:00:00","total":-776} + {"index": {"_id":"1180"}} + {"timestamp":"2017-03-23T13:00:00","total":11366} + {"index": {"_id":"1181"}} + {"timestamp":"2017-03-23T13:00:00","total":3606} + {"index": {"_id":"1182"}} + {"timestamp":"2017-03-23T13:00:00","total":19006} + {"index": {"_id":"1183"}} + {"timestamp":"2017-03-23T13:00:00","total":38613} + {"index": {"_id":"1184"}} + {"timestamp":"2017-03-23T13:00:00","total":19516} + {"index": {"_id":"1185"}} + {"timestamp":"2017-03-23T13:00:00","total":-258} + {"index": {"_id":"1186"}} + {"timestamp":"2017-03-23T13:00:00","total":9551} + {"index": {"_id":"1187"}} + {"timestamp":"2017-03-23T13:00:00","total":11217} + {"index": {"_id":"1188"}} + {"timestamp":"2017-03-23T13:00:00","total":22557} + {"index": {"_id":"1189"}} + {"timestamp":"2017-03-23T13:00:00","total":40508} + {"index": {"_id":"1190"}} + {"timestamp":"2017-03-23T13:00:00","total":11887} + {"index": {"_id":"1191"}} + {"timestamp":"2017-03-23T13:00:00","total":31659} +''' +setups['server_metrics_job'] = setups['server_metrics_data'] + ''' + - do: + xpack.ml.put_job: + job_id: "total-requests" + body: > + { + "description" : "Total sum of requests", + "analysis_config" : { + "bucket_span":"10m", + "detectors" :[ + { + "detector_description": "Sum of total", + "function": "sum", + "field_name": "total" + } + ]}, + "data_description" : { + "time_field":"timestamp", + "time_format": "epoch_ms" + } + } +''' +setups['server_metrics_datafeed'] = setups['server_metrics_job'] + ''' + - do: + xpack.ml.put_datafeed: + datafeed_id: "datafeed-total-requests" + body: > + { + "job_id":"total-requests", + "indexes":"server-metrics" + } +''' +setups['server_metrics_openjob'] = setups['server_metrics_datafeed'] + ''' + - do: + xpack.ml.open_job: + job_id: "total-requests" +''' +setups['server_metrics_startdf'] = setups['server_metrics_openjob'] + ''' + - do: + xpack.ml.start_datafeed: + datafeed_id: "datafeed-total-requests" +''' +setups['calendar_outages'] = ''' + - do: + xpack.ml.put_calendar: + calendar_id: "planned-outages" +''' +setups['calendar_outages_addevent'] = setups['calendar_outages'] + ''' + - do: + xpack.ml.post_calendar_events: + calendar_id: "planned-outages" + body: > + { "description": "event 1", "start_time": "2017-12-01T00:00:00Z", "end_time": "2017-12-02T00:00:00Z", "calendar_id": "planned-outages" } + + +''' +setups['calendar_outages_openjob'] = setups['server_metrics_openjob'] + ''' + - do: + xpack.ml.put_calendar: + calendar_id: "planned-outages" +''' +setups['calendar_outages_addjob'] = setups['server_metrics_openjob'] + ''' + - do: + xpack.ml.put_calendar: + calendar_id: "planned-outages" + body: > + { + "job_ids": ["total-requests"] + } +''' +setups['calendar_outages_addevent'] = setups['calendar_outages_addjob'] + ''' + - do: + xpack.ml.post_calendar_events: + calendar_id: "planned-outages" + body: > + { "events" : [ + { "description": "event 1", "start_time": "1513641600000", "end_time": "1513728000000"}, + { "description": "event 2", "start_time": "1513814400000", "end_time": "1513900800000"}, + { "description": "event 3", "start_time": "1514160000000", "end_time": "1514246400000"} + ]} +''' +setups['role_mapping'] = ''' + - do: + xpack.security.put_role_mapping: + name: "mapping1" + body: > + { + "enabled": true, + "roles": [ "user" ], + "rules": { "field": { "username": "*" } } + } +''' +setups['sensor_rollup_job'] = ''' + - do: + indices.create: + index: sensor-1 + body: + settings: + number_of_shards: 1 + number_of_replicas: 0 + mappings: + _doc: + properties: + timestamp: + type: date + temperature: + type: long + voltage: + type: float + node: + type: keyword + - do: + xpack.rollup.put_job: + id: "sensor" + body: > + { + "index_pattern": "sensor-*", + "rollup_index": "sensor_rollup", + "cron": "*/30 * * * * ?", + "page_size" :1000, + "groups" : { + "date_histogram": { + "field": "timestamp", + "interval": "1h", + "delay": "7d" + }, + "terms": { + "fields": ["node"] + } + }, + "metrics": [ + { + "field": "temperature", + "metrics": ["min", "max", "sum"] + }, + { + "field": "voltage", + "metrics": ["avg"] + } + ] + } +''' +setups['sensor_started_rollup_job'] = ''' + - do: + indices.create: + index: sensor-1 + body: + settings: + number_of_shards: 1 + number_of_replicas: 0 + mappings: + _doc: + properties: + timestamp: + type: date + temperature: + type: long + voltage: + type: float + node: + type: keyword + + - do: + bulk: + index: sensor-1 + type: _doc + refresh: true + body: | + {"index":{}} + {"timestamp": 1516729294000, "temperature": 200, "voltage": 5.2, "node": "a"} + {"index":{}} + {"timestamp": 1516642894000, "temperature": 201, "voltage": 5.8, "node": "b"} + {"index":{}} + {"timestamp": 1516556494000, "temperature": 202, "voltage": 5.1, "node": "a"} + {"index":{}} + {"timestamp": 1516470094000, "temperature": 198, "voltage": 5.6, "node": "b"} + {"index":{}} + {"timestamp": 1516383694000, "temperature": 200, "voltage": 4.2, "node": "c"} + {"index":{}} + {"timestamp": 1516297294000, "temperature": 202, "voltage": 4.0, "node": "c"} + + - do: + xpack.rollup.put_job: + id: "sensor" + body: > + { + "index_pattern": "sensor-*", + "rollup_index": "sensor_rollup", + "cron": "* * * * * ?", + "page_size" :1000, + "groups" : { + "date_histogram": { + "field": "timestamp", + "interval": "1h", + "delay": "7d" + }, + "terms": { + "fields": ["node"] + } + }, + "metrics": [ + { + "field": "temperature", + "metrics": ["min", "max", "sum"] + }, + { + "field": "voltage", + "metrics": ["avg"] + } + ] + } + - do: + xpack.rollup.start_job: + id: "sensor" +''' + +setups['sensor_index'] = ''' + - do: + indices.create: + index: sensor-1 + body: + settings: + number_of_shards: 1 + number_of_replicas: 0 + mappings: + _doc: + properties: + timestamp: + type: date + temperature: + type: long + voltage: + type: float + node: + type: keyword + load: + type: double + net_in: + type: long + net_out: + type: long + hostname: + type: keyword + datacenter: + type: keyword +''' + +setups['sensor_prefab_data'] = ''' + - do: + indices.create: + index: sensor-1 + body: + settings: + number_of_shards: 1 + number_of_replicas: 0 + mappings: + _doc: + properties: + timestamp: + type: date + temperature: + type: long + voltage: + type: float + node: + type: keyword + - do: + indices.create: + index: sensor_rollup + body: + settings: + number_of_shards: 1 + number_of_replicas: 0 + mappings: + _doc: + properties: + node.terms.value: + type: keyword + temperature.sum.value: + type: double + temperature.max.value: + type: double + temperature.min.value: + type: double + timestamp.date_histogram.time_zone: + type: keyword + timestamp.date_histogram.interval: + type: keyword + timestamp.date_histogram.timestamp: + type: date + timestamp.date_histogram._count: + type: long + voltage.avg.value: + type: double + voltage.avg._count: + type: long + _rollup.id: + type: keyword + _rollup.version: + type: long + _meta: + _rollup: + sensor: + cron: "* * * * * ?" + rollup_index: "sensor_rollup" + index_pattern: "sensor-*" + timeout: "20s" + page_size: 1000 + groups: + date_histogram: + delay: "7d" + field: "timestamp" + interval: "1h" + time_zone: "UTC" + terms: + fields: + - "node" + id: sensor + metrics: + - field: "temperature" + metrics: + - min + - max + - sum + - field: "voltage" + metrics: + - avg + + - do: + bulk: + index: sensor_rollup + type: _doc + refresh: true + body: | + {"index":{}} + {"node.terms.value":"b","temperature.sum.value":201.0,"temperature.max.value":201.0,"timestamp.date_histogram.time_zone":"UTC","temperature.min.value":201.0,"timestamp.date_histogram._count":1,"timestamp.date_histogram.interval":"1h","_rollup.computed":["temperature.sum","temperature.min","voltage.avg","temperature.max","node.terms","timestamp.date_histogram"],"voltage.avg.value":5.800000190734863,"node.terms._count":1,"_rollup.version":1,"timestamp.date_histogram.timestamp":1516640400000,"voltage.avg._count":1.0,"_rollup.id":"sensor"} + {"index":{}} + {"node.terms.value":"c","temperature.sum.value":200.0,"temperature.max.value":200.0,"timestamp.date_histogram.time_zone":"UTC","temperature.min.value":200.0,"timestamp.date_histogram._count":1,"timestamp.date_histogram.interval":"1h","_rollup.computed":["temperature.sum","temperature.min","voltage.avg","temperature.max","node.terms","timestamp.date_histogram"],"voltage.avg.value":4.199999809265137,"node.terms._count":1,"_rollup.version":1,"timestamp.date_histogram.timestamp":1516381200000,"voltage.avg._count":1.0,"_rollup.id":"sensor"} + {"index":{}} + {"node.terms.value":"a","temperature.sum.value":202.0,"temperature.max.value":202.0,"timestamp.date_histogram.time_zone":"UTC","temperature.min.value":202.0,"timestamp.date_histogram._count":1,"timestamp.date_histogram.interval":"1h","_rollup.computed":["temperature.sum","temperature.min","voltage.avg","temperature.max","node.terms","timestamp.date_histogram"],"voltage.avg.value":5.099999904632568,"node.terms._count":1,"_rollup.version":1,"timestamp.date_histogram.timestamp":1516554000000,"voltage.avg._count":1.0,"_rollup.id":"sensor"} + {"index":{}} + {"node.terms.value":"a","temperature.sum.value":200.0,"temperature.max.value":200.0,"timestamp.date_histogram.time_zone":"UTC","temperature.min.value":200.0,"timestamp.date_histogram._count":1,"timestamp.date_histogram.interval":"1h","_rollup.computed":["temperature.sum","temperature.min","voltage.avg","temperature.max","node.terms","timestamp.date_histogram"],"voltage.avg.value":5.199999809265137,"node.terms._count":1,"_rollup.version":1,"timestamp.date_histogram.timestamp":1516726800000,"voltage.avg._count":1.0,"_rollup.id":"sensor"} + {"index":{}} + {"node.terms.value":"b","temperature.sum.value":198.0,"temperature.max.value":198.0,"timestamp.date_histogram.time_zone":"UTC","temperature.min.value":198.0,"timestamp.date_histogram._count":1,"timestamp.date_histogram.interval":"1h","_rollup.computed":["temperature.sum","temperature.min","voltage.avg","temperature.max","node.terms","timestamp.date_histogram"],"voltage.avg.value":5.599999904632568,"node.terms._count":1,"_rollup.version":1,"timestamp.date_histogram.timestamp":1516467600000,"voltage.avg._count":1.0,"_rollup.id":"sensor"} + {"index":{}} + {"node.terms.value":"c","temperature.sum.value":202.0,"temperature.max.value":202.0,"timestamp.date_histogram.time_zone":"UTC","temperature.min.value":202.0,"timestamp.date_histogram._count":1,"timestamp.date_histogram.interval":"1h","_rollup.computed":["temperature.sum","temperature.min","voltage.avg","temperature.max","node.terms","timestamp.date_histogram"],"voltage.avg.value":4.0,"node.terms._count":1,"_rollup.version":1,"timestamp.date_histogram.timestamp":1516294800000,"voltage.avg._count":1.0,"_rollup.id":"sensor"} + +''' diff --git a/x-pack/docs/en/rest-api/license/start-trial.asciidoc b/x-pack/docs/en/rest-api/license/start-trial.asciidoc index 8ff793455a239..7754f6feef79c 100644 --- a/x-pack/docs/en/rest-api/license/start-trial.asciidoc +++ b/x-pack/docs/en/rest-api/license/start-trial.asciidoc @@ -40,7 +40,7 @@ The following example checks whether you are eligible to start a trial: [source,js] ------------------------------------------------------------ -POST _xpack/license/start_trial +GET _xpack/license/start_trial ------------------------------------------------------------ // CONSOLE // TEST[skip:license testing issues] @@ -49,6 +49,27 @@ Example response: [source,js] ------------------------------------------------------------ { - "trial_was_started": true + "eligible_to_start_trial": true } ------------------------------------------------------------ +// NOTCONSOLE + +The following example starts a 30-day trial license. The acknowledge +parameter is required as you are initiating a license that will expire. + +[source,js] +------------------------------------------------------------ +POST _xpack/license/start_trial?acknowledge=true +------------------------------------------------------------ +// CONSOLE +// TEST[skip:license testing issues] + +Example response: +[source,js] +------------------------------------------------------------ +{ + "trial_was_started": true, + "acknowledged": true +} +------------------------------------------------------------ +// NOTCONSOLE \ No newline at end of file diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicensingClient.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicensingClient.java index d2d4461b93108..21381b376925d 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicensingClient.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicensingClient.java @@ -41,11 +41,11 @@ public void deleteLicense(DeleteLicenseRequest request, ActionListener listener) { + client.execute(PutLicenseAction.INSTANCE, request, listener); + } + + public GetLicenseRequestBuilder prepareGetLicense() { + return new GetLicenseRequestBuilder(client); + } + + public void getLicense(GetLicenseRequest request, ActionListener listener) { + client.execute(GetLicenseAction.INSTANCE, request, listener); + } + + public DeleteLicenseRequestBuilder prepareDeleteLicense() { + return new DeleteLicenseRequestBuilder(client); + } + + public void deleteLicense(DeleteLicenseRequest request, ActionListener listener) { + client.execute(DeleteLicenseAction.INSTANCE, request, listener); + } + + public PostStartTrialRequestBuilder preparePostUpgradeToTrial() { + return new PostStartTrialRequestBuilder(client, PostStartTrialAction.INSTANCE); + } + + public GetTrialStatusRequestBuilder prepareGetUpgradeToTrial() { + return new GetTrialStatusRequestBuilder(client, GetTrialStatusAction.INSTANCE); + } + + public void postStartTrial(PostStartTrialRequest request, ActionListener listener) { + client.execute(PostStartTrialAction.INSTANCE, request, listener); + } + + public void postStartBasic(PostStartBasicRequest request, ActionListener listener) { + client.execute(PostStartBasicAction.INSTANCE, request, listener); + } + + public PostStartBasicRequestBuilder preparePostStartBasic() { + return new PostStartBasicRequestBuilder(client, PostStartBasicAction.INSTANCE); + } + + public GetBasicStatusRequestBuilder prepareGetStartBasic() { + return new GetBasicStatusRequestBuilder(client, GetBasicStatusAction.INSTANCE); + } +} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequest.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequest.java index 882db4d622adf..c6293646c09f7 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequest.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequest.java @@ -15,6 +15,7 @@ public class PostStartTrialRequest extends MasterNodeRequest { + private boolean acknowledge = false; private String type; @Override @@ -31,25 +32,47 @@ public String getType() { return type; } + public PostStartTrialRequest acknowledge(boolean acknowledge) { + this.acknowledge = acknowledge; + return this; + } + + public boolean isAcknowledged() { + return acknowledge; + } + @Override public void readFrom(StreamInput in) throws IOException { super.readFrom(in); if (in.getVersion().onOrAfter(Version.V_6_3_0)) { type = in.readString(); + acknowledge = in.readBoolean(); } else { type = "trial"; + acknowledge = true; } } @Override public void writeTo(StreamOutput out) throws IOException { - super.writeTo(out); - Version version = Version.V_6_3_0; + // TODO: Change to 6.3 after backport + Version version = Version.V_7_0_0_alpha1; if (out.getVersion().onOrAfter(version)) { + super.writeTo(out); out.writeString(type); + out.writeBoolean(acknowledge); } else { - throw new IllegalArgumentException("All nodes in cluster must be version [" + version - + "] or newer to use `type` parameter. Attempting to write to node with version [" + out.getVersion() + "]."); + if ("trial".equals(type) == false) { + throw new IllegalArgumentException("All nodes in cluster must be version [" + version + + "] or newer to start trial with a different type than 'trial'. Attempting to write to " + + "a node with version [" + out.getVersion() + "] with trial type [" + type + "]."); + } else if (acknowledge == false) { + throw new IllegalArgumentException("Request must be acknowledged to send to a node with a version " + + "prior to [" + version + "]. Attempting to send request to node with version [" + out.getVersion() + "] " + + "without acknowledgement."); + } else { + super.writeTo(out); + } } } } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequest.java.orig b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequest.java.orig new file mode 100644 index 0000000000000..882db4d622adf --- /dev/null +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequest.java.orig @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.license; + +import org.elasticsearch.Version; +import org.elasticsearch.action.ActionRequestValidationException; +import org.elasticsearch.action.support.master.MasterNodeRequest; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; + +import java.io.IOException; + +public class PostStartTrialRequest extends MasterNodeRequest { + + private String type; + + @Override + public ActionRequestValidationException validate() { + return null; + } + + public PostStartTrialRequest setType(String type) { + this.type = type; + return this; + } + + public String getType() { + return type; + } + + @Override + public void readFrom(StreamInput in) throws IOException { + super.readFrom(in); + if (in.getVersion().onOrAfter(Version.V_6_3_0)) { + type = in.readString(); + } else { + type = "trial"; + } + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + Version version = Version.V_6_3_0; + if (out.getVersion().onOrAfter(version)) { + out.writeString(type); + } else { + throw new IllegalArgumentException("All nodes in cluster must be version [" + version + + "] or newer to use `type` parameter. Attempting to write to node with version [" + out.getVersion() + "]."); + } + } +} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequestBuilder.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequestBuilder.java index af381e13517f8..6b0beba171bdd 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequestBuilder.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequestBuilder.java @@ -14,4 +14,9 @@ class PostStartTrialRequestBuilder extends ActionRequestBuilder { + + PostStartTrialRequestBuilder(ElasticsearchClient client, PostStartTrialAction action) { + super(client, action, new PostStartTrialRequest()); + } +} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java index dcbdbfb6abda0..efe4ae1754e80 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java @@ -5,23 +5,33 @@ */ package org.elasticsearch.license; +import org.elasticsearch.Version; import org.elasticsearch.action.ActionResponse; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.rest.RestStatus; import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; class PostStartTrialResponse extends ActionResponse { + // Nodes Prior to 6.3 did not have NEED_ACKNOWLEDGEMENT as part of status + enum Pre63Status { + UPGRADED_TO_TRIAL, + TRIAL_ALREADY_ACTIVATED; + } enum Status { UPGRADED_TO_TRIAL(true, null, RestStatus.OK), - TRIAL_ALREADY_ACTIVATED(false, "Operation failed: Trial was already activated.", RestStatus.FORBIDDEN); + TRIAL_ALREADY_ACTIVATED(false, "Operation failed: Trial was already activated.", RestStatus.FORBIDDEN), + NEED_ACKNOWLEDGEMENT(false,"Operation failed: Needs acknowledgement.", RestStatus.OK); private final boolean isTrialStarted; + private final String errorMessage; private final RestStatus restStatus; - Status(boolean isTrialStarted, String errorMessage, RestStatus restStatus) { this.isTrialStarted = isTrialStarted; this.errorMessage = errorMessage; @@ -39,15 +49,24 @@ String getErrorMessage() { RestStatus getRestStatus() { return restStatus; } + } private Status status; + private Map acknowledgeMessages; + private String acknowledgeMessage; PostStartTrialResponse() { } PostStartTrialResponse(Status status) { + this(status, Collections.emptyMap(), null); + } + + PostStartTrialResponse(Status status, Map acknowledgeMessages, String acknowledgeMessage) { this.status = status; + this.acknowledgeMessages = acknowledgeMessages; + this.acknowledgeMessage = acknowledgeMessage; } public Status getStatus() { @@ -57,10 +76,57 @@ public Status getStatus() { @Override public void readFrom(StreamInput in) throws IOException { status = in.readEnum(Status.class); + if (in.getVersion().onOrAfter(Version.V_6_3_0)) { + acknowledgeMessage = in.readOptionalString(); + int size = in.readVInt(); + Map acknowledgeMessages = new HashMap<>(size); + for (int i = 0; i < size; i++) { + String feature = in.readString(); + int nMessages = in.readVInt(); + String[] messages = new String[nMessages]; + for (int j = 0; j < nMessages; j++) { + messages[j] = in.readString(); + } + acknowledgeMessages.put(feature, messages); + } + this.acknowledgeMessages = acknowledgeMessages; + } else { + this.acknowledgeMessages = Collections.emptyMap(); + } } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeEnum(status); + // TODO: Change to 6.3 after backport + Version version = Version.V_7_0_0_alpha1; + if (out.getVersion().onOrAfter(version)) { + out.writeEnum(status); + out.writeOptionalString(acknowledgeMessage); + out.writeVInt(acknowledgeMessages.size()); + for (Map.Entry entry : acknowledgeMessages.entrySet()) { + out.writeString(entry.getKey()); + out.writeVInt(entry.getValue().length); + for (String message : entry.getValue()) { + out.writeString(message); + } + } + } else { + if (status == Status.UPGRADED_TO_TRIAL) { + out.writeEnum(Pre63Status.UPGRADED_TO_TRIAL); + } else if (status == Status.TRIAL_ALREADY_ACTIVATED) { + out.writeEnum(Pre63Status.TRIAL_ALREADY_ACTIVATED); + } else { + throw new IllegalArgumentException("Starting trial on node with version [" + Version.CURRENT + "] requires " + + "acknowledgement parameter."); + } + } + } + + Map getAcknowledgementMessages() { + return acknowledgeMessages; + } + + String getAcknowledgementMessage() { + return acknowledgeMessage; } } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java.orig b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java.orig new file mode 100644 index 0000000000000..dcbdbfb6abda0 --- /dev/null +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java.orig @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.license; + +import org.elasticsearch.action.ActionResponse; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.rest.RestStatus; + +import java.io.IOException; + +class PostStartTrialResponse extends ActionResponse { + + enum Status { + UPGRADED_TO_TRIAL(true, null, RestStatus.OK), + TRIAL_ALREADY_ACTIVATED(false, "Operation failed: Trial was already activated.", RestStatus.FORBIDDEN); + + private final boolean isTrialStarted; + private final String errorMessage; + private final RestStatus restStatus; + + Status(boolean isTrialStarted, String errorMessage, RestStatus restStatus) { + this.isTrialStarted = isTrialStarted; + this.errorMessage = errorMessage; + this.restStatus = restStatus; + } + + boolean isTrialStarted() { + return isTrialStarted; + } + + String getErrorMessage() { + return errorMessage; + } + + RestStatus getRestStatus() { + return restStatus; + } + } + + private Status status; + + PostStartTrialResponse() { + } + + PostStartTrialResponse(Status status) { + this.status = status; + } + + public Status getStatus() { + return status; + } + + @Override + public void readFrom(StreamInput in) throws IOException { + status = in.readEnum(Status.class); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeEnum(status); + } +} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestGetTrialStatus.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestGetTrialStatus.java index ebd43318ff91e..a136f2a88a65d 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestGetTrialStatus.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestGetTrialStatus.java @@ -29,7 +29,7 @@ public class RestGetTrialStatus extends XPackRestHandler { @Override protected RestChannelConsumer doPrepareRequest(RestRequest request, XPackClient client) throws IOException { - return channel -> client.licensing().prepareGetUpgradeToTrial().execute( + return channel -> client.licensing().prepareGetStartTrial().execute( new RestBuilderListener(channel) { @Override public RestResponse buildResponse(GetTrialStatusResponse response, XContentBuilder builder) throws Exception { diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestGetTrialStatus.java.orig b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestGetTrialStatus.java.orig new file mode 100644 index 0000000000000..ebd43318ff91e --- /dev/null +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestGetTrialStatus.java.orig @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.license; + +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.rest.BytesRestResponse; +import org.elasticsearch.rest.RestController; +import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.rest.RestResponse; +import org.elasticsearch.rest.RestStatus; +import org.elasticsearch.rest.action.RestBuilderListener; +import org.elasticsearch.xpack.core.XPackClient; +import org.elasticsearch.xpack.core.rest.XPackRestHandler; + +import java.io.IOException; + +import static org.elasticsearch.rest.RestRequest.Method.GET; + +public class RestGetTrialStatus extends XPackRestHandler { + + RestGetTrialStatus(Settings settings, RestController controller) { + super(settings); + controller.registerHandler(GET, URI_BASE + "/license/trial_status", this); + } + + @Override + protected RestChannelConsumer doPrepareRequest(RestRequest request, XPackClient client) throws IOException { + return channel -> client.licensing().prepareGetUpgradeToTrial().execute( + new RestBuilderListener(channel) { + @Override + public RestResponse buildResponse(GetTrialStatusResponse response, XContentBuilder builder) throws Exception { + builder.startObject(); + builder.field("eligible_to_start_trial", response.isEligibleToStartTrial()); + builder.endObject(); + return new BytesRestResponse(RestStatus.OK, builder); + } + }); + } + + @Override + public String getName() { + return "xpack_trial_status_action"; + } +} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestPostStartTrialLicense.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestPostStartTrialLicense.java index 0332eedd69dd1..af738b9aadf7f 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestPostStartTrialLicense.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestPostStartTrialLicense.java @@ -16,6 +16,7 @@ import org.elasticsearch.xpack.core.rest.XPackRestHandler; import java.io.IOException; +import java.util.Map; import static org.elasticsearch.rest.RestRequest.Method.POST; @@ -30,23 +31,36 @@ public class RestPostStartTrialLicense extends XPackRestHandler { protected RestChannelConsumer doPrepareRequest(RestRequest request, XPackClient client) throws IOException { PostStartTrialRequest startTrialRequest = new PostStartTrialRequest(); startTrialRequest.setType(request.param("type", "trial")); + startTrialRequest.acknowledge(request.paramAsBoolean("acknowledge", false)); return channel -> client.licensing().postStartTrial(startTrialRequest, new RestBuilderListener(channel) { @Override public RestResponse buildResponse(PostStartTrialResponse response, XContentBuilder builder) throws Exception { PostStartTrialResponse.Status status = response.getStatus(); + builder.startObject(); + builder.field("acknowledged", startTrialRequest.isAcknowledged()); if (status.isTrialStarted()) { - builder.startObject() - .field("trial_was_started", true) - .field("type", startTrialRequest.getType()) - .endObject(); + builder.field("trial_was_started", true); + builder.field("type", startTrialRequest.getType()); } else { - builder.startObject() - .field("trial_was_started", false) - .field("error_message", status.getErrorMessage()) - .endObject(); + builder.field("trial_was_started", false); + builder.field("error_message", status.getErrorMessage()); + } + Map acknowledgementMessages = response.getAcknowledgementMessages(); + if (acknowledgementMessages.isEmpty() == false) { + builder.startObject("acknowledge"); + builder.field("message", response.getAcknowledgementMessage()); + for (Map.Entry entry : acknowledgementMessages.entrySet()) { + builder.startArray(entry.getKey()); + for (String message : entry.getValue()) { + builder.value(message); + } + builder.endArray(); + } + builder.endObject(); } + builder.endObject(); return new BytesRestResponse(status.getRestStatus(), builder); } }); diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestPostStartTrialLicense.java.orig b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestPostStartTrialLicense.java.orig new file mode 100644 index 0000000000000..0332eedd69dd1 --- /dev/null +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestPostStartTrialLicense.java.orig @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.license; + +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.rest.BytesRestResponse; +import org.elasticsearch.rest.RestController; +import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.rest.RestResponse; +import org.elasticsearch.rest.action.RestBuilderListener; +import org.elasticsearch.xpack.core.XPackClient; +import org.elasticsearch.xpack.core.rest.XPackRestHandler; + +import java.io.IOException; + +import static org.elasticsearch.rest.RestRequest.Method.POST; + +public class RestPostStartTrialLicense extends XPackRestHandler { + + RestPostStartTrialLicense(Settings settings, RestController controller) { + super(settings); + controller.registerHandler(POST, URI_BASE + "/license/start_trial", this); + } + + @Override + protected RestChannelConsumer doPrepareRequest(RestRequest request, XPackClient client) throws IOException { + PostStartTrialRequest startTrialRequest = new PostStartTrialRequest(); + startTrialRequest.setType(request.param("type", "trial")); + return channel -> client.licensing().postStartTrial(startTrialRequest, + new RestBuilderListener(channel) { + @Override + public RestResponse buildResponse(PostStartTrialResponse response, XContentBuilder builder) throws Exception { + PostStartTrialResponse.Status status = response.getStatus(); + if (status.isTrialStarted()) { + builder.startObject() + .field("trial_was_started", true) + .field("type", startTrialRequest.getType()) + .endObject(); + } else { + builder.startObject() + .field("trial_was_started", false) + .field("error_message", status.getErrorMessage()) + .endObject(); + + } + return new BytesRestResponse(status.getRestStatus(), builder); + } + }); + } + + @Override + public String getName() { + return "xpack_upgrade_to_trial_action"; + } +} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartTrialClusterTask.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartTrialClusterTask.java index 3ca8dbf0eaa4e..355672dedf717 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartTrialClusterTask.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartTrialClusterTask.java @@ -15,10 +15,23 @@ import org.elasticsearch.common.Nullable; import java.time.Clock; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; public class StartTrialClusterTask extends ClusterStateUpdateTask { + private static final String ACKNOWLEDGEMENT_HEADER = "This API initiates a free 30-day trial for all platinum features. " + + "By starting this trial, you agree that it is subject to the terms and conditions at" + + " https://www.elastic.co/legal/trial_license/. To begin your free trial, call /start_trial again and specify " + + "the \"acknowledge=true\" parameter."; + + private static final Map ACK_MESSAGES = Collections.singletonMap("security", + new String[] {"With a trial license, X-Pack security features are available, but are not enabled by default."}); + private final Logger logger; private final String clusterName; private final PostStartTrialRequest request; @@ -39,7 +52,10 @@ public void clusterStateProcessed(String source, ClusterState oldState, ClusterS LicensesMetaData oldLicensesMetaData = oldState.metaData().custom(LicensesMetaData.TYPE); logger.debug("started self generated trial license: {}", oldLicensesMetaData); - if (oldLicensesMetaData == null || oldLicensesMetaData.isEligibleForTrial()) { + if (request.isAcknowledged() == false) { + listener.onResponse(new PostStartTrialResponse(PostStartTrialResponse.Status.NEED_ACKNOWLEDGEMENT, + ACK_MESSAGES, ACKNOWLEDGEMENT_HEADER)); + } else if (oldLicensesMetaData == null || oldLicensesMetaData.isEligibleForTrial()) { listener.onResponse(new PostStartTrialResponse(PostStartTrialResponse.Status.UPGRADED_TO_TRIAL)); } else { listener.onResponse(new PostStartTrialResponse(PostStartTrialResponse.Status.TRIAL_ALREADY_ACTIVATED)); @@ -50,7 +66,9 @@ public void clusterStateProcessed(String source, ClusterState oldState, ClusterS public ClusterState execute(ClusterState currentState) throws Exception { LicensesMetaData currentLicensesMetaData = currentState.metaData().custom(LicensesMetaData.TYPE); - if (currentLicensesMetaData == null || currentLicensesMetaData.isEligibleForTrial()) { + if (request.isAcknowledged() == false) { + return currentState; + } else if (currentLicensesMetaData == null || currentLicensesMetaData.isEligibleForTrial()) { long issueDate = clock.millis(); MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData()); long expiryDate = issueDate + LicenseService.NON_BASIC_SELF_GENERATED_LICENSE_DURATION.getMillis(); diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartTrialClusterTask.java.orig b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartTrialClusterTask.java.orig new file mode 100644 index 0000000000000..3ca8dbf0eaa4e --- /dev/null +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartTrialClusterTask.java.orig @@ -0,0 +1,79 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.license; + +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.message.ParameterizedMessage; +import org.elasticsearch.Version; +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.ClusterStateUpdateTask; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.common.Nullable; + +import java.time.Clock; +import java.util.UUID; + +public class StartTrialClusterTask extends ClusterStateUpdateTask { + + private final Logger logger; + private final String clusterName; + private final PostStartTrialRequest request; + private final ActionListener listener; + private final Clock clock; + + StartTrialClusterTask(Logger logger, String clusterName, Clock clock, PostStartTrialRequest request, + ActionListener listener) { + this.logger = logger; + this.clusterName = clusterName; + this.request = request; + this.listener = listener; + this.clock = clock; + } + + @Override + public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) { + LicensesMetaData oldLicensesMetaData = oldState.metaData().custom(LicensesMetaData.TYPE); + logger.debug("started self generated trial license: {}", oldLicensesMetaData); + + if (oldLicensesMetaData == null || oldLicensesMetaData.isEligibleForTrial()) { + listener.onResponse(new PostStartTrialResponse(PostStartTrialResponse.Status.UPGRADED_TO_TRIAL)); + } else { + listener.onResponse(new PostStartTrialResponse(PostStartTrialResponse.Status.TRIAL_ALREADY_ACTIVATED)); + } + } + + @Override + public ClusterState execute(ClusterState currentState) throws Exception { + LicensesMetaData currentLicensesMetaData = currentState.metaData().custom(LicensesMetaData.TYPE); + + if (currentLicensesMetaData == null || currentLicensesMetaData.isEligibleForTrial()) { + long issueDate = clock.millis(); + MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData()); + long expiryDate = issueDate + LicenseService.NON_BASIC_SELF_GENERATED_LICENSE_DURATION.getMillis(); + + License.Builder specBuilder = License.builder() + .uid(UUID.randomUUID().toString()) + .issuedTo(clusterName) + .maxNodes(LicenseService.SELF_GENERATED_LICENSE_MAX_NODES) + .issueDate(issueDate) + .type(request.getType()) + .expiryDate(expiryDate); + License selfGeneratedLicense = SelfGeneratedLicense.create(specBuilder); + LicensesMetaData newLicensesMetaData = new LicensesMetaData(selfGeneratedLicense, Version.CURRENT); + mdBuilder.putCustom(LicensesMetaData.TYPE, newLicensesMetaData); + return ClusterState.builder(currentState).metaData(mdBuilder).build(); + } else { + return currentState; + } + } + + @Override + public void onFailure(String source, @Nullable Exception e) { + logger.error(new ParameterizedMessage("unexpected failure during [{}]", source), e); + listener.onFailure(e); + } +} diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartTrialLicenseTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartTrialLicenseTests.java index d673c4e720452..b7a09d24b1359 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartTrialLicenseTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartTrialLicenseTests.java @@ -56,33 +56,47 @@ public void testStartTrial() throws Exception { assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals("{\"eligible_to_start_trial\":true}", body); - String type = randomFrom(LicenseService.VALID_TRIAL_TYPES); - - Response response2 = restClient.performRequest("POST", "/_xpack/license/start_trial?type=" + type); + // Test that starting will fail without acknowledgement + Response response2 = restClient.performRequest("POST", "/_xpack/license/start_trial"); String body2 = Streams.copyToString(new InputStreamReader(response2.getEntity().getContent(), StandardCharsets.UTF_8)); assertEquals(200, response2.getStatusLine().getStatusCode()); - assertTrue(body2.contains("\"trial_was_started\":true")); - assertTrue(body2.contains("\"type\":\"" + type + "\"")); + assertTrue(body2.contains("\"trial_was_started\":false")); + assertTrue(body2.contains("\"error_message\":\"Operation failed: Needs acknowledgement.\"")); + assertTrue(body2.contains("\"acknowledged\":false")); assertBusy(() -> { - GetLicenseResponse postTrialLicenseResponse = licensingClient.prepareGetLicense().get(); - assertEquals(type, postTrialLicenseResponse.license().type()); + GetLicenseResponse getLicenseResponse = licensingClient.prepareGetLicense().get(); + assertEquals("basic", getLicenseResponse.license().type()); }); - Response response3 = restClient.performRequest("GET", "/_xpack/license/trial_status"); + String type = randomFrom(LicenseService.VALID_TRIAL_TYPES); + + Response response3 = restClient.performRequest("POST", "/_xpack/license/start_trial?acknowledge=true&type=" + type); String body3 = Streams.copyToString(new InputStreamReader(response3.getEntity().getContent(), StandardCharsets.UTF_8)); assertEquals(200, response3.getStatusLine().getStatusCode()); - assertEquals("{\"eligible_to_start_trial\":false}", body3); + assertTrue(body3.contains("\"trial_was_started\":true")); + assertTrue(body3.contains("\"type\":\"" + type + "\"")); + assertTrue(body3.contains("\"acknowledged\":true")); + + assertBusy(() -> { + GetLicenseResponse postTrialLicenseResponse = licensingClient.prepareGetLicense().get(); + assertEquals(type, postTrialLicenseResponse.license().type()); + }); + + Response response4 = restClient.performRequest("GET", "/_xpack/license/trial_status"); + String body4 = Streams.copyToString(new InputStreamReader(response4.getEntity().getContent(), StandardCharsets.UTF_8)); + assertEquals(200, response4.getStatusLine().getStatusCode()); + assertEquals("{\"eligible_to_start_trial\":false}", body4); String secondAttemptType = randomFrom(LicenseService.VALID_TRIAL_TYPES); ResponseException ex = expectThrows(ResponseException.class, - () -> restClient.performRequest("POST", "/_xpack/license/start_trial?type=" + secondAttemptType)); - Response response4 = ex.getResponse(); - String body4 = Streams.copyToString(new InputStreamReader(response4.getEntity().getContent(), StandardCharsets.UTF_8)); - assertEquals(403, response4.getStatusLine().getStatusCode()); - assertTrue(body4.contains("\"trial_was_started\":false")); - assertTrue(body4.contains("\"error_message\":\"Operation failed: Trial was already activated.\"")); + () -> restClient.performRequest("POST", "/_xpack/license/start_trial?acknowledge=true&type=" + secondAttemptType)); + Response response5 = ex.getResponse(); + String body5 = Streams.copyToString(new InputStreamReader(response5.getEntity().getContent(), StandardCharsets.UTF_8)); + assertEquals(403, response5.getStatusLine().getStatusCode()); + assertTrue(body5.contains("\"trial_was_started\":false")); + assertTrue(body5.contains("\"error_message\":\"Operation failed: Trial was already activated.\"")); } public void testInvalidType() throws Exception { diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartTrialLicenseTests.java.orig b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartTrialLicenseTests.java.orig new file mode 100644 index 0000000000000..d673c4e720452 --- /dev/null +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartTrialLicenseTests.java.orig @@ -0,0 +1,113 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.license; + +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseException; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.common.io.Streams; +import org.elasticsearch.common.network.NetworkModule; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.test.ESIntegTestCase; +import org.elasticsearch.transport.Netty4Plugin; +import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin; +import org.elasticsearch.xpack.core.XPackClientPlugin; + +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collection; + +import static org.elasticsearch.test.ESIntegTestCase.Scope.SUITE; + +@ESIntegTestCase.ClusterScope(scope = SUITE) +public class StartTrialLicenseTests extends AbstractLicensesIntegrationTestCase { + + @Override + protected Settings nodeSettings(int nodeOrdinal) { + return Settings.builder() + .put(super.nodeSettings(nodeOrdinal)) + .put("node.data", true) + .put(LicenseService.SELF_GENERATED_LICENSE_TYPE.getKey(), "basic") + .put(NetworkModule.HTTP_ENABLED.getKey(), true).build(); + } + + @Override + protected Collection> nodePlugins() { + return Arrays.asList(LocalStateCompositeXPackPlugin.class, Netty4Plugin.class); + } + + @Override + protected Collection> transportClientPlugins() { + return Arrays.asList(XPackClientPlugin.class, Netty4Plugin.class); + } + + public void testStartTrial() throws Exception { + LicensingClient licensingClient = new LicensingClient(client()); + ensureStartingWithBasic(); + + RestClient restClient = getRestClient(); + Response response = restClient.performRequest("GET", "/_xpack/license/trial_status"); + String body = Streams.copyToString(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)); + assertEquals(200, response.getStatusLine().getStatusCode()); + assertEquals("{\"eligible_to_start_trial\":true}", body); + + String type = randomFrom(LicenseService.VALID_TRIAL_TYPES); + + Response response2 = restClient.performRequest("POST", "/_xpack/license/start_trial?type=" + type); + String body2 = Streams.copyToString(new InputStreamReader(response2.getEntity().getContent(), StandardCharsets.UTF_8)); + assertEquals(200, response2.getStatusLine().getStatusCode()); + assertTrue(body2.contains("\"trial_was_started\":true")); + assertTrue(body2.contains("\"type\":\"" + type + "\"")); + + assertBusy(() -> { + GetLicenseResponse postTrialLicenseResponse = licensingClient.prepareGetLicense().get(); + assertEquals(type, postTrialLicenseResponse.license().type()); + }); + + Response response3 = restClient.performRequest("GET", "/_xpack/license/trial_status"); + String body3 = Streams.copyToString(new InputStreamReader(response3.getEntity().getContent(), StandardCharsets.UTF_8)); + assertEquals(200, response3.getStatusLine().getStatusCode()); + assertEquals("{\"eligible_to_start_trial\":false}", body3); + + String secondAttemptType = randomFrom(LicenseService.VALID_TRIAL_TYPES); + + ResponseException ex = expectThrows(ResponseException.class, + () -> restClient.performRequest("POST", "/_xpack/license/start_trial?type=" + secondAttemptType)); + Response response4 = ex.getResponse(); + String body4 = Streams.copyToString(new InputStreamReader(response4.getEntity().getContent(), StandardCharsets.UTF_8)); + assertEquals(403, response4.getStatusLine().getStatusCode()); + assertTrue(body4.contains("\"trial_was_started\":false")); + assertTrue(body4.contains("\"error_message\":\"Operation failed: Trial was already activated.\"")); + } + + public void testInvalidType() throws Exception { + ensureStartingWithBasic(); + + ResponseException ex = expectThrows(ResponseException.class, () -> + getRestClient().performRequest("POST", "/_xpack/license/start_trial?type=basic")); + Response response = ex.getResponse(); + String body = Streams.copyToString(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)); + assertEquals(400, response.getStatusLine().getStatusCode()); + assertTrue(body.contains("\"type\":\"illegal_argument_exception\"")); + assertTrue(body.contains("\"reason\":\"Cannot start trial of type [basic]. Valid trial types are [")); + } + + private void ensureStartingWithBasic() throws Exception { + LicensingClient licensingClient = new LicensingClient(client()); + GetLicenseResponse getLicenseResponse = licensingClient.prepareGetLicense().get(); + + if ("basic".equals(getLicenseResponse.license().type()) == false) { + licensingClient.preparePostStartBasic().setAcknowledge(true).get(); + } + + assertBusy(() -> { + GetLicenseResponse postTrialLicenseResponse = licensingClient.prepareGetLicense().get(); + assertEquals("basic", postTrialLicenseResponse.license().type()); + }); + } +} diff --git a/x-pack/plugin/src/test/resources/rest-api-spec/api/xpack.license.post_start_trial.json b/x-pack/plugin/src/test/resources/rest-api-spec/api/xpack.license.post_start_trial.json index 688afc7b79bbf..a1e5d27da1eda 100644 --- a/x-pack/plugin/src/test/resources/rest-api-spec/api/xpack.license.post_start_trial.json +++ b/x-pack/plugin/src/test/resources/rest-api-spec/api/xpack.license.post_start_trial.json @@ -11,6 +11,10 @@ "type": { "type" : "string", "description" : "The type of trial license to generate (default: \"trial\")" + }, + "acknowledge": { + "type" : "boolean", + "description" : "whether the user has acknowledged acknowledge messages (default: false)" } } }, diff --git a/x-pack/plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yml b/x-pack/plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yml index 98e96318d7a19..9eb3b79fda7a7 100644 --- a/x-pack/plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yml +++ b/x-pack/plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yml @@ -133,7 +133,8 @@ teardown: - do: catch: forbidden - xpack.license.post_start_trial: {} + xpack.license.post_start_trial: + acknowledge: true - match: { trial_was_started: false } - match: { error_message: "Operation failed: Trial was already activated." } @@ -143,6 +144,7 @@ teardown: catch: bad_request xpack.license.post_start_trial: type: "basic" + acknowledge: true --- "Can start basic license if do not already have basic": - do: From a5d0c81ecc00a7725549bc210533de26a96dffe4 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Wed, 25 Apr 2018 12:03:27 -0600 Subject: [PATCH 2/3] Delete files --- x-pack/docs/build.gradle.orig | 687 ------------------ .../license/LicensingClient.java.orig | 67 -- .../license/PostStartTrialRequest.java.orig | 55 -- .../PostStartTrialRequestBuilder.java.orig | 17 - .../license/PostStartTrialResponse.java.orig | 66 -- .../license/RestGetTrialStatus.java.orig | 48 -- .../RestPostStartTrialLicense.java.orig | 59 -- .../license/StartTrialClusterTask.java.orig | 79 -- .../license/StartTrialLicenseTests.java.orig | 113 --- 9 files changed, 1191 deletions(-) delete mode 100644 x-pack/docs/build.gradle.orig delete mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicensingClient.java.orig delete mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequest.java.orig delete mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequestBuilder.java.orig delete mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java.orig delete mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestGetTrialStatus.java.orig delete mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestPostStartTrialLicense.java.orig delete mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartTrialClusterTask.java.orig delete mode 100644 x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartTrialLicenseTests.java.orig diff --git a/x-pack/docs/build.gradle.orig b/x-pack/docs/build.gradle.orig deleted file mode 100644 index ae851732daac8..0000000000000 --- a/x-pack/docs/build.gradle.orig +++ /dev/null @@ -1,687 +0,0 @@ -import org.elasticsearch.gradle.test.NodeInfo - -import java.nio.charset.StandardCharsets - -apply plugin: 'elasticsearch.docs-test' - -/* List of files that have snippets that probably should be converted to - * `// CONSOLE` and `// TESTRESPONSE` but have yet to be converted. Try and - * only remove entries from this list. When it is empty we'll remove it - * entirely and have a party! There will be cake and everything.... */ -buildRestTests.expectedUnconvertedCandidates = [ - 'en/ml/functions/count.asciidoc', - 'en/ml/functions/geo.asciidoc', - 'en/ml/functions/info.asciidoc', - 'en/ml/functions/metric.asciidoc', - 'en/ml/functions/rare.asciidoc', - 'en/ml/functions/sum.asciidoc', - 'en/ml/functions/time.asciidoc', - 'en/ml/aggregations.asciidoc', - 'en/ml/customurl.asciidoc', - 'en/monitoring/indices.asciidoc', - 'en/rest-api/security/ssl.asciidoc', - 'en/rest-api/security/users.asciidoc', - 'en/rest-api/security/tokens.asciidoc', - 'en/rest-api/watcher/put-watch.asciidoc', - 'en/security/authentication/user-cache.asciidoc', - 'en/security/authorization/field-and-document-access-control.asciidoc', - 'en/security/authorization/run-as-privilege.asciidoc', - 'en/security/ccs-clients-integrations/http.asciidoc', - 'en/security/authorization/custom-roles-provider.asciidoc', - 'en/watcher/actions/email.asciidoc', - 'en/watcher/actions/hipchat.asciidoc', - 'en/watcher/actions/index.asciidoc', - 'en/watcher/actions/logging.asciidoc', - 'en/watcher/actions/pagerduty.asciidoc', - 'en/watcher/actions/slack.asciidoc', - 'en/watcher/actions/jira.asciidoc', - 'en/watcher/actions/webhook.asciidoc', - 'en/watcher/condition/always.asciidoc', - 'en/watcher/condition/array-compare.asciidoc', - 'en/watcher/condition/compare.asciidoc', - 'en/watcher/condition/never.asciidoc', - 'en/watcher/condition/script.asciidoc', - 'en/watcher/customizing-watches.asciidoc', - 'en/watcher/example-watches/example-watch-meetupdata.asciidoc', - 'en/watcher/how-watcher-works.asciidoc', - 'en/watcher/input/chain.asciidoc', - 'en/watcher/input/http.asciidoc', - 'en/watcher/input/search.asciidoc', - 'en/watcher/input/simple.asciidoc', - 'en/watcher/transform.asciidoc', - 'en/watcher/transform/chain.asciidoc', - 'en/watcher/transform/script.asciidoc', - 'en/watcher/transform/search.asciidoc', - 'en/watcher/trigger/schedule/cron.asciidoc', - 'en/watcher/trigger/schedule/daily.asciidoc', - 'en/watcher/trigger/schedule/hourly.asciidoc', - 'en/watcher/trigger/schedule/interval.asciidoc', - 'en/watcher/trigger/schedule/monthly.asciidoc', - 'en/watcher/trigger/schedule/weekly.asciidoc', - 'en/watcher/trigger/schedule/yearly.asciidoc', - 'en/watcher/troubleshooting.asciidoc', - 'en/rest-api/license/delete-license.asciidoc', - 'en/rest-api/license/start-trial.asciidoc', - 'en/rest-api/license/update-license.asciidoc', - 'en/ml/api-quickref.asciidoc', - 'en/rest-api/ml/delete-calendar-event.asciidoc', - 'en/rest-api/ml/delete-snapshot.asciidoc', - 'en/rest-api/ml/forecast.asciidoc', - 'en/rest-api/ml/get-bucket.asciidoc', - 'en/rest-api/ml/get-job-stats.asciidoc', - 'en/rest-api/ml/get-overall-buckets.asciidoc', - 'en/rest-api/ml/get-category.asciidoc', - 'en/rest-api/ml/get-record.asciidoc', - 'en/rest-api/ml/get-influencer.asciidoc', - 'en/rest-api/ml/get-snapshot.asciidoc', - 'en/rest-api/ml/post-data.asciidoc', - 'en/rest-api/ml/preview-datafeed.asciidoc', - 'en/rest-api/ml/revert-snapshot.asciidoc', - 'en/rest-api/ml/update-snapshot.asciidoc', - 'en/rest-api/ml/validate-detector.asciidoc', - 'en/rest-api/ml/validate-job.asciidoc', - 'en/rest-api/security/authenticate.asciidoc', - 'en/rest-api/watcher/stats.asciidoc', - 'en/security/authorization.asciidoc', - 'en/watcher/example-watches/watching-time-series-data.asciidoc', -] - -dependencies { - testCompile project(path: xpackModule('core'), configuration: 'runtime') - testCompile project(path: xpackModule('core'), configuration: 'testArtifacts') - testCompile project(path: xpackProject('plugin').path, configuration: 'testArtifacts') -} - -Closure waitWithAuth = { NodeInfo node, AntBuilder ant -> - File tmpFile = new File(node.cwd, 'wait.success') - // wait up to twenty seconds - final long stopTime = System.currentTimeMillis() + 20000L; - Exception lastException = null; - while (System.currentTimeMillis() < stopTime) { - lastException = null; - // we use custom wait logic here as the elastic user is not available immediately and ant.get will fail when a 401 is returned - HttpURLConnection httpURLConnection = null; - try { - httpURLConnection = (HttpURLConnection) new URL("http://${node.httpUri()}/_cluster/health").openConnection(); - httpURLConnection.setRequestProperty("Authorization", "Basic " + - Base64.getEncoder().encodeToString("test_admin:x-pack-test-password".getBytes(StandardCharsets.UTF_8))); - httpURLConnection.setRequestMethod("GET"); - httpURLConnection.setConnectTimeout(1000); - httpURLConnection.setReadTimeout(30000); - httpURLConnection.connect(); - if (httpURLConnection.getResponseCode() == 200) { - tmpFile.withWriter StandardCharsets.UTF_8.name(), { - it.write(httpURLConnection.getInputStream().getText(StandardCharsets.UTF_8.name())) - } - break; - } - } catch (Exception e) { - logger.debug("failed to call cluster health", e) - lastException = e - } finally { - if (httpURLConnection != null) { - httpURLConnection.disconnect(); - } - } - - // did not start, so wait a bit before trying again - Thread.sleep(500L); - } - if (tmpFile.exists() == false && lastException != null) { - logger.error("final attempt of calling cluster health failed", lastException) - } - return tmpFile.exists() -} - -// copy xpack rest api -File xpackResources = new File(xpackProject('plugin').projectDir, 'src/test/resources') -project.copyRestSpec.from(xpackResources) { - include 'rest-api-spec/api/**' -} -integTestCluster { - setting 'xpack.security.enabled', 'true' - setting 'xpack.security.authc.token.enabled', 'true' - // Disable monitoring exporters for the docs tests - setting 'xpack.monitoring.exporters._local.type', 'local' - setting 'xpack.monitoring.exporters._local.enabled', 'false' - setting 'xpack.license.self_generated.type', 'trial' - setupCommand 'setupTestAdmin', - 'bin/elasticsearch-users', 'useradd', 'test_admin', '-p', 'x-pack-test-password', '-r', 'superuser' - waitCondition = waitWithAuth -} - - - -buildRestTests.docs = fileTree(projectDir) { - // No snippets in here! - exclude 'build.gradle' - // That is where the snippets go, not where they come from! - exclude 'build' - // These file simply doesn't pass yet. We should figure out how to fix them. - exclude 'en/watcher/reference/actions.asciidoc' - exclude 'en/rest-api/graph/explore.asciidoc' -} - -Map setups = buildRestTests.setups -setups['my_inactive_watch'] = ''' - - do: - xpack.watcher.put_watch: - id: "my_watch" - active: false - body: > - { - "trigger": { - "schedule": { - "hourly": { - "minute": [ 0, 5 ] - } - } - }, - "input": { - "simple": { - "payload": { - "send": "yes" - } - } - }, - "condition": { - "always": {} - }, - "actions": { - "test_index": { - "index": { - "index": "test", - "doc_type": "test2" - } - } - } - } - - match: { _id: "my_watch" } -''' -setups['my_active_watch'] = setups['my_inactive_watch'].replace( - 'active: false', 'active: true') - -// Used by SQL because it looks SQL-ish -setups['library'] = ''' - - do: - indices.create: - index: library - body: - settings: - number_of_shards: 1 - number_of_replicas: 1 - mappings: - book: - properties: - name: - type: text - fields: - keyword: - type: keyword - author: - type: text - fields: - keyword: - type: keyword - release_date: - type: date - page_count: - type: short - - do: - bulk: - index: library - type: book - refresh: true - body: | - {"index":{"_id": "Leviathan Wakes"}} - {"name": "Leviathan Wakes", "author": "James S.A. Corey", "release_date": "2011-06-02", "page_count": 561} - {"index":{"_id": "Hyperion"}} - {"name": "Hyperion", "author": "Dan Simmons", "release_date": "1989-05-26", "page_count": 482} - {"index":{"_id": "Dune"}} - {"name": "Dune", "author": "Frank Herbert", "release_date": "1965-06-01", "page_count": 604} - {"index":{"_id": "Dune Messiah"}} - {"name": "Dune Messiah", "author": "Frank Herbert", "release_date": "1969-10-15", "page_count": 331} - {"index":{"_id": "Children of Dune"}} - {"name": "Children of Dune", "author": "Frank Herbert", "release_date": "1976-04-21", "page_count": 408} - {"index":{"_id": "God Emperor of Dune"}} - {"name": "God Emperor of Dune", "author": "Frank Herbert", "release_date": "1981-05-28", "page_count": 454} - {"index":{"_id": "Consider Phlebas"}} - {"name": "Consider Phlebas", "author": "Iain M. Banks", "release_date": "1987-04-23", "page_count": 471} - {"index":{"_id": "Pandora's Star"}} - {"name": "Pandora's Star", "author": "Peter F. Hamilton", "release_date": "2004-03-02", "page_count": 768} - {"index":{"_id": "Revelation Space"}} - {"name": "Revelation Space", "author": "Alastair Reynolds", "release_date": "2000-03-15", "page_count": 585} - {"index":{"_id": "A Fire Upon the Deep"}} - {"name": "A Fire Upon the Deep", "author": "Vernor Vinge", "release_date": "1992-06-01", "page_count": 613} - {"index":{"_id": "Ender's Game"}} - {"name": "Ender's Game", "author": "Orson Scott Card", "release_date": "1985-06-01", "page_count": 324} - {"index":{"_id": "1984"}} - {"name": "1984", "author": "George Orwell", "release_date": "1985-06-01", "page_count": 328} - {"index":{"_id": "Fahrenheit 451"}} - {"name": "Fahrenheit 451", "author": "Ray Bradbury", "release_date": "1953-10-15", "page_count": 227} - {"index":{"_id": "Brave New World"}} - {"name": "Brave New World", "author": "Aldous Huxley", "release_date": "1932-06-01", "page_count": 268} - {"index":{"_id": "Foundation"}} - {"name": "Foundation", "author": "Isaac Asimov", "release_date": "1951-06-01", "page_count": 224} - {"index":{"_id": "The Giver"}} - {"name": "The Giver", "author": "Lois Lowry", "release_date": "1993-04-26", "page_count": 208} - {"index":{"_id": "Slaughterhouse-Five"}} - {"name": "Slaughterhouse-Five", "author": "Kurt Vonnegut", "release_date": "1969-06-01", "page_count": 275} - {"index":{"_id": "The Hitchhiker's Guide to the Galaxy"}} - {"name": "The Hitchhiker's Guide to the Galaxy", "author": "Douglas Adams", "release_date": "1979-10-12", "page_count": 180} - {"index":{"_id": "Snow Crash"}} - {"name": "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "page_count": 470} - {"index":{"_id": "Neuromancer"}} - {"name": "Neuromancer", "author": "William Gibson", "release_date": "1984-07-01", "page_count": 271} - {"index":{"_id": "The Handmaid's Tale"}} - {"name": "The Handmaid's Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311} - {"index":{"_id": "Starship Troopers"}} - {"name": "Starship Troopers", "author": "Robert A. Heinlein", "release_date": "1959-12-01", "page_count": 335} - {"index":{"_id": "The Left Hand of Darkness"}} - {"name": "The Left Hand of Darkness", "author": "Ursula K. Le Guin", "release_date": "1969-06-01", "page_count": 304} - {"index":{"_id": "The Moon is a Harsh Mistress"}} - {"name": "The Moon is a Harsh Mistress", "author": "Robert A. Heinlein", "release_date": "1966-04-01", "page_count": 288} - -''' -setups['server_metrics_index'] = ''' - - do: - indices.create: - index: server-metrics - body: - settings: - number_of_shards: 1 - number_of_replicas: 0 - mappings: - metric: - properties: - timestamp: - type: date - total: - type: long -''' -setups['server_metrics_data'] = setups['server_metrics_index'] + ''' - - do: - bulk: - index: server-metrics - type: metric - refresh: true - body: | - {"index": {"_id":"1177"}} - {"timestamp":"2017-03-23T13:00:00","total":40476} - {"index": {"_id":"1178"}} - {"timestamp":"2017-03-23T13:00:00","total":15287} - {"index": {"_id":"1179"}} - {"timestamp":"2017-03-23T13:00:00","total":-776} - {"index": {"_id":"1180"}} - {"timestamp":"2017-03-23T13:00:00","total":11366} - {"index": {"_id":"1181"}} - {"timestamp":"2017-03-23T13:00:00","total":3606} - {"index": {"_id":"1182"}} - {"timestamp":"2017-03-23T13:00:00","total":19006} - {"index": {"_id":"1183"}} - {"timestamp":"2017-03-23T13:00:00","total":38613} - {"index": {"_id":"1184"}} - {"timestamp":"2017-03-23T13:00:00","total":19516} - {"index": {"_id":"1185"}} - {"timestamp":"2017-03-23T13:00:00","total":-258} - {"index": {"_id":"1186"}} - {"timestamp":"2017-03-23T13:00:00","total":9551} - {"index": {"_id":"1187"}} - {"timestamp":"2017-03-23T13:00:00","total":11217} - {"index": {"_id":"1188"}} - {"timestamp":"2017-03-23T13:00:00","total":22557} - {"index": {"_id":"1189"}} - {"timestamp":"2017-03-23T13:00:00","total":40508} - {"index": {"_id":"1190"}} - {"timestamp":"2017-03-23T13:00:00","total":11887} - {"index": {"_id":"1191"}} - {"timestamp":"2017-03-23T13:00:00","total":31659} -''' -setups['server_metrics_job'] = setups['server_metrics_data'] + ''' - - do: - xpack.ml.put_job: - job_id: "total-requests" - body: > - { - "description" : "Total sum of requests", - "analysis_config" : { - "bucket_span":"10m", - "detectors" :[ - { - "detector_description": "Sum of total", - "function": "sum", - "field_name": "total" - } - ]}, - "data_description" : { - "time_field":"timestamp", - "time_format": "epoch_ms" - } - } -''' -setups['server_metrics_datafeed'] = setups['server_metrics_job'] + ''' - - do: - xpack.ml.put_datafeed: - datafeed_id: "datafeed-total-requests" - body: > - { - "job_id":"total-requests", - "indexes":"server-metrics" - } -''' -setups['server_metrics_openjob'] = setups['server_metrics_datafeed'] + ''' - - do: - xpack.ml.open_job: - job_id: "total-requests" -''' -setups['server_metrics_startdf'] = setups['server_metrics_openjob'] + ''' - - do: - xpack.ml.start_datafeed: - datafeed_id: "datafeed-total-requests" -''' -setups['calendar_outages'] = ''' - - do: - xpack.ml.put_calendar: - calendar_id: "planned-outages" -''' -setups['calendar_outages_addevent'] = setups['calendar_outages'] + ''' - - do: - xpack.ml.post_calendar_events: - calendar_id: "planned-outages" - body: > - { "description": "event 1", "start_time": "2017-12-01T00:00:00Z", "end_time": "2017-12-02T00:00:00Z", "calendar_id": "planned-outages" } - - -''' -setups['calendar_outages_openjob'] = setups['server_metrics_openjob'] + ''' - - do: - xpack.ml.put_calendar: - calendar_id: "planned-outages" -''' -setups['calendar_outages_addjob'] = setups['server_metrics_openjob'] + ''' - - do: - xpack.ml.put_calendar: - calendar_id: "planned-outages" - body: > - { - "job_ids": ["total-requests"] - } -''' -setups['calendar_outages_addevent'] = setups['calendar_outages_addjob'] + ''' - - do: - xpack.ml.post_calendar_events: - calendar_id: "planned-outages" - body: > - { "events" : [ - { "description": "event 1", "start_time": "1513641600000", "end_time": "1513728000000"}, - { "description": "event 2", "start_time": "1513814400000", "end_time": "1513900800000"}, - { "description": "event 3", "start_time": "1514160000000", "end_time": "1514246400000"} - ]} -''' -setups['role_mapping'] = ''' - - do: - xpack.security.put_role_mapping: - name: "mapping1" - body: > - { - "enabled": true, - "roles": [ "user" ], - "rules": { "field": { "username": "*" } } - } -''' -setups['sensor_rollup_job'] = ''' - - do: - indices.create: - index: sensor-1 - body: - settings: - number_of_shards: 1 - number_of_replicas: 0 - mappings: - _doc: - properties: - timestamp: - type: date - temperature: - type: long - voltage: - type: float - node: - type: keyword - - do: - xpack.rollup.put_job: - id: "sensor" - body: > - { - "index_pattern": "sensor-*", - "rollup_index": "sensor_rollup", - "cron": "*/30 * * * * ?", - "page_size" :1000, - "groups" : { - "date_histogram": { - "field": "timestamp", - "interval": "1h", - "delay": "7d" - }, - "terms": { - "fields": ["node"] - } - }, - "metrics": [ - { - "field": "temperature", - "metrics": ["min", "max", "sum"] - }, - { - "field": "voltage", - "metrics": ["avg"] - } - ] - } -''' -setups['sensor_started_rollup_job'] = ''' - - do: - indices.create: - index: sensor-1 - body: - settings: - number_of_shards: 1 - number_of_replicas: 0 - mappings: - _doc: - properties: - timestamp: - type: date - temperature: - type: long - voltage: - type: float - node: - type: keyword - - - do: - bulk: - index: sensor-1 - type: _doc - refresh: true - body: | - {"index":{}} - {"timestamp": 1516729294000, "temperature": 200, "voltage": 5.2, "node": "a"} - {"index":{}} - {"timestamp": 1516642894000, "temperature": 201, "voltage": 5.8, "node": "b"} - {"index":{}} - {"timestamp": 1516556494000, "temperature": 202, "voltage": 5.1, "node": "a"} - {"index":{}} - {"timestamp": 1516470094000, "temperature": 198, "voltage": 5.6, "node": "b"} - {"index":{}} - {"timestamp": 1516383694000, "temperature": 200, "voltage": 4.2, "node": "c"} - {"index":{}} - {"timestamp": 1516297294000, "temperature": 202, "voltage": 4.0, "node": "c"} - - - do: - xpack.rollup.put_job: - id: "sensor" - body: > - { - "index_pattern": "sensor-*", - "rollup_index": "sensor_rollup", - "cron": "* * * * * ?", - "page_size" :1000, - "groups" : { - "date_histogram": { - "field": "timestamp", - "interval": "1h", - "delay": "7d" - }, - "terms": { - "fields": ["node"] - } - }, - "metrics": [ - { - "field": "temperature", - "metrics": ["min", "max", "sum"] - }, - { - "field": "voltage", - "metrics": ["avg"] - } - ] - } - - do: - xpack.rollup.start_job: - id: "sensor" -''' - -setups['sensor_index'] = ''' - - do: - indices.create: - index: sensor-1 - body: - settings: - number_of_shards: 1 - number_of_replicas: 0 - mappings: - _doc: - properties: - timestamp: - type: date - temperature: - type: long - voltage: - type: float - node: - type: keyword - load: - type: double - net_in: - type: long - net_out: - type: long - hostname: - type: keyword - datacenter: - type: keyword -''' - -setups['sensor_prefab_data'] = ''' - - do: - indices.create: - index: sensor-1 - body: - settings: - number_of_shards: 1 - number_of_replicas: 0 - mappings: - _doc: - properties: - timestamp: - type: date - temperature: - type: long - voltage: - type: float - node: - type: keyword - - do: - indices.create: - index: sensor_rollup - body: - settings: - number_of_shards: 1 - number_of_replicas: 0 - mappings: - _doc: - properties: - node.terms.value: - type: keyword - temperature.sum.value: - type: double - temperature.max.value: - type: double - temperature.min.value: - type: double - timestamp.date_histogram.time_zone: - type: keyword - timestamp.date_histogram.interval: - type: keyword - timestamp.date_histogram.timestamp: - type: date - timestamp.date_histogram._count: - type: long - voltage.avg.value: - type: double - voltage.avg._count: - type: long - _rollup.id: - type: keyword - _rollup.version: - type: long - _meta: - _rollup: - sensor: - cron: "* * * * * ?" - rollup_index: "sensor_rollup" - index_pattern: "sensor-*" - timeout: "20s" - page_size: 1000 - groups: - date_histogram: - delay: "7d" - field: "timestamp" - interval: "1h" - time_zone: "UTC" - terms: - fields: - - "node" - id: sensor - metrics: - - field: "temperature" - metrics: - - min - - max - - sum - - field: "voltage" - metrics: - - avg - - - do: - bulk: - index: sensor_rollup - type: _doc - refresh: true - body: | - {"index":{}} - {"node.terms.value":"b","temperature.sum.value":201.0,"temperature.max.value":201.0,"timestamp.date_histogram.time_zone":"UTC","temperature.min.value":201.0,"timestamp.date_histogram._count":1,"timestamp.date_histogram.interval":"1h","_rollup.computed":["temperature.sum","temperature.min","voltage.avg","temperature.max","node.terms","timestamp.date_histogram"],"voltage.avg.value":5.800000190734863,"node.terms._count":1,"_rollup.version":1,"timestamp.date_histogram.timestamp":1516640400000,"voltage.avg._count":1.0,"_rollup.id":"sensor"} - {"index":{}} - {"node.terms.value":"c","temperature.sum.value":200.0,"temperature.max.value":200.0,"timestamp.date_histogram.time_zone":"UTC","temperature.min.value":200.0,"timestamp.date_histogram._count":1,"timestamp.date_histogram.interval":"1h","_rollup.computed":["temperature.sum","temperature.min","voltage.avg","temperature.max","node.terms","timestamp.date_histogram"],"voltage.avg.value":4.199999809265137,"node.terms._count":1,"_rollup.version":1,"timestamp.date_histogram.timestamp":1516381200000,"voltage.avg._count":1.0,"_rollup.id":"sensor"} - {"index":{}} - {"node.terms.value":"a","temperature.sum.value":202.0,"temperature.max.value":202.0,"timestamp.date_histogram.time_zone":"UTC","temperature.min.value":202.0,"timestamp.date_histogram._count":1,"timestamp.date_histogram.interval":"1h","_rollup.computed":["temperature.sum","temperature.min","voltage.avg","temperature.max","node.terms","timestamp.date_histogram"],"voltage.avg.value":5.099999904632568,"node.terms._count":1,"_rollup.version":1,"timestamp.date_histogram.timestamp":1516554000000,"voltage.avg._count":1.0,"_rollup.id":"sensor"} - {"index":{}} - {"node.terms.value":"a","temperature.sum.value":200.0,"temperature.max.value":200.0,"timestamp.date_histogram.time_zone":"UTC","temperature.min.value":200.0,"timestamp.date_histogram._count":1,"timestamp.date_histogram.interval":"1h","_rollup.computed":["temperature.sum","temperature.min","voltage.avg","temperature.max","node.terms","timestamp.date_histogram"],"voltage.avg.value":5.199999809265137,"node.terms._count":1,"_rollup.version":1,"timestamp.date_histogram.timestamp":1516726800000,"voltage.avg._count":1.0,"_rollup.id":"sensor"} - {"index":{}} - {"node.terms.value":"b","temperature.sum.value":198.0,"temperature.max.value":198.0,"timestamp.date_histogram.time_zone":"UTC","temperature.min.value":198.0,"timestamp.date_histogram._count":1,"timestamp.date_histogram.interval":"1h","_rollup.computed":["temperature.sum","temperature.min","voltage.avg","temperature.max","node.terms","timestamp.date_histogram"],"voltage.avg.value":5.599999904632568,"node.terms._count":1,"_rollup.version":1,"timestamp.date_histogram.timestamp":1516467600000,"voltage.avg._count":1.0,"_rollup.id":"sensor"} - {"index":{}} - {"node.terms.value":"c","temperature.sum.value":202.0,"temperature.max.value":202.0,"timestamp.date_histogram.time_zone":"UTC","temperature.min.value":202.0,"timestamp.date_histogram._count":1,"timestamp.date_histogram.interval":"1h","_rollup.computed":["temperature.sum","temperature.min","voltage.avg","temperature.max","node.terms","timestamp.date_histogram"],"voltage.avg.value":4.0,"node.terms._count":1,"_rollup.version":1,"timestamp.date_histogram.timestamp":1516294800000,"voltage.avg._count":1.0,"_rollup.id":"sensor"} - -''' diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicensingClient.java.orig b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicensingClient.java.orig deleted file mode 100644 index d2d4461b93108..0000000000000 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicensingClient.java.orig +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.license; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.client.ElasticsearchClient; -import org.elasticsearch.rest.action.RestBuilderListener; - -public class LicensingClient { - - private final ElasticsearchClient client; - - public LicensingClient(ElasticsearchClient client) { - this.client = client; - } - - public PutLicenseRequestBuilder preparePutLicense(License license) { - return new PutLicenseRequestBuilder(client).setLicense(license); - } - - public void putLicense(PutLicenseRequest request, ActionListener listener) { - client.execute(PutLicenseAction.INSTANCE, request, listener); - } - - public GetLicenseRequestBuilder prepareGetLicense() { - return new GetLicenseRequestBuilder(client); - } - - public void getLicense(GetLicenseRequest request, ActionListener listener) { - client.execute(GetLicenseAction.INSTANCE, request, listener); - } - - public DeleteLicenseRequestBuilder prepareDeleteLicense() { - return new DeleteLicenseRequestBuilder(client); - } - - public void deleteLicense(DeleteLicenseRequest request, ActionListener listener) { - client.execute(DeleteLicenseAction.INSTANCE, request, listener); - } - - public PostStartTrialRequestBuilder preparePostUpgradeToTrial() { - return new PostStartTrialRequestBuilder(client, PostStartTrialAction.INSTANCE); - } - - public GetTrialStatusRequestBuilder prepareGetUpgradeToTrial() { - return new GetTrialStatusRequestBuilder(client, GetTrialStatusAction.INSTANCE); - } - - public void postStartTrial(PostStartTrialRequest request, ActionListener listener) { - client.execute(PostStartTrialAction.INSTANCE, request, listener); - } - - public void postStartBasic(PostStartBasicRequest request, ActionListener listener) { - client.execute(PostStartBasicAction.INSTANCE, request, listener); - } - - public PostStartBasicRequestBuilder preparePostStartBasic() { - return new PostStartBasicRequestBuilder(client, PostStartBasicAction.INSTANCE); - } - - public GetBasicStatusRequestBuilder prepareGetStartBasic() { - return new GetBasicStatusRequestBuilder(client, GetBasicStatusAction.INSTANCE); - } -} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequest.java.orig b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequest.java.orig deleted file mode 100644 index 882db4d622adf..0000000000000 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequest.java.orig +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.license; - -import org.elasticsearch.Version; -import org.elasticsearch.action.ActionRequestValidationException; -import org.elasticsearch.action.support.master.MasterNodeRequest; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; - -import java.io.IOException; - -public class PostStartTrialRequest extends MasterNodeRequest { - - private String type; - - @Override - public ActionRequestValidationException validate() { - return null; - } - - public PostStartTrialRequest setType(String type) { - this.type = type; - return this; - } - - public String getType() { - return type; - } - - @Override - public void readFrom(StreamInput in) throws IOException { - super.readFrom(in); - if (in.getVersion().onOrAfter(Version.V_6_3_0)) { - type = in.readString(); - } else { - type = "trial"; - } - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - super.writeTo(out); - Version version = Version.V_6_3_0; - if (out.getVersion().onOrAfter(version)) { - out.writeString(type); - } else { - throw new IllegalArgumentException("All nodes in cluster must be version [" + version - + "] or newer to use `type` parameter. Attempting to write to node with version [" + out.getVersion() + "]."); - } - } -} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequestBuilder.java.orig b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequestBuilder.java.orig deleted file mode 100644 index af381e13517f8..0000000000000 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialRequestBuilder.java.orig +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.license; - -import org.elasticsearch.action.ActionRequestBuilder; -import org.elasticsearch.client.ElasticsearchClient; - -class PostStartTrialRequestBuilder extends ActionRequestBuilder { - - PostStartTrialRequestBuilder(ElasticsearchClient client, PostStartTrialAction action) { - super(client, action, new PostStartTrialRequest()); - } -} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java.orig b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java.orig deleted file mode 100644 index dcbdbfb6abda0..0000000000000 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java.orig +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.license; - -import org.elasticsearch.action.ActionResponse; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.rest.RestStatus; - -import java.io.IOException; - -class PostStartTrialResponse extends ActionResponse { - - enum Status { - UPGRADED_TO_TRIAL(true, null, RestStatus.OK), - TRIAL_ALREADY_ACTIVATED(false, "Operation failed: Trial was already activated.", RestStatus.FORBIDDEN); - - private final boolean isTrialStarted; - private final String errorMessage; - private final RestStatus restStatus; - - Status(boolean isTrialStarted, String errorMessage, RestStatus restStatus) { - this.isTrialStarted = isTrialStarted; - this.errorMessage = errorMessage; - this.restStatus = restStatus; - } - - boolean isTrialStarted() { - return isTrialStarted; - } - - String getErrorMessage() { - return errorMessage; - } - - RestStatus getRestStatus() { - return restStatus; - } - } - - private Status status; - - PostStartTrialResponse() { - } - - PostStartTrialResponse(Status status) { - this.status = status; - } - - public Status getStatus() { - return status; - } - - @Override - public void readFrom(StreamInput in) throws IOException { - status = in.readEnum(Status.class); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeEnum(status); - } -} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestGetTrialStatus.java.orig b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestGetTrialStatus.java.orig deleted file mode 100644 index ebd43318ff91e..0000000000000 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestGetTrialStatus.java.orig +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.license; - -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.rest.BytesRestResponse; -import org.elasticsearch.rest.RestController; -import org.elasticsearch.rest.RestRequest; -import org.elasticsearch.rest.RestResponse; -import org.elasticsearch.rest.RestStatus; -import org.elasticsearch.rest.action.RestBuilderListener; -import org.elasticsearch.xpack.core.XPackClient; -import org.elasticsearch.xpack.core.rest.XPackRestHandler; - -import java.io.IOException; - -import static org.elasticsearch.rest.RestRequest.Method.GET; - -public class RestGetTrialStatus extends XPackRestHandler { - - RestGetTrialStatus(Settings settings, RestController controller) { - super(settings); - controller.registerHandler(GET, URI_BASE + "/license/trial_status", this); - } - - @Override - protected RestChannelConsumer doPrepareRequest(RestRequest request, XPackClient client) throws IOException { - return channel -> client.licensing().prepareGetUpgradeToTrial().execute( - new RestBuilderListener(channel) { - @Override - public RestResponse buildResponse(GetTrialStatusResponse response, XContentBuilder builder) throws Exception { - builder.startObject(); - builder.field("eligible_to_start_trial", response.isEligibleToStartTrial()); - builder.endObject(); - return new BytesRestResponse(RestStatus.OK, builder); - } - }); - } - - @Override - public String getName() { - return "xpack_trial_status_action"; - } -} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestPostStartTrialLicense.java.orig b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestPostStartTrialLicense.java.orig deleted file mode 100644 index 0332eedd69dd1..0000000000000 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/RestPostStartTrialLicense.java.orig +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.license; - -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.rest.BytesRestResponse; -import org.elasticsearch.rest.RestController; -import org.elasticsearch.rest.RestRequest; -import org.elasticsearch.rest.RestResponse; -import org.elasticsearch.rest.action.RestBuilderListener; -import org.elasticsearch.xpack.core.XPackClient; -import org.elasticsearch.xpack.core.rest.XPackRestHandler; - -import java.io.IOException; - -import static org.elasticsearch.rest.RestRequest.Method.POST; - -public class RestPostStartTrialLicense extends XPackRestHandler { - - RestPostStartTrialLicense(Settings settings, RestController controller) { - super(settings); - controller.registerHandler(POST, URI_BASE + "/license/start_trial", this); - } - - @Override - protected RestChannelConsumer doPrepareRequest(RestRequest request, XPackClient client) throws IOException { - PostStartTrialRequest startTrialRequest = new PostStartTrialRequest(); - startTrialRequest.setType(request.param("type", "trial")); - return channel -> client.licensing().postStartTrial(startTrialRequest, - new RestBuilderListener(channel) { - @Override - public RestResponse buildResponse(PostStartTrialResponse response, XContentBuilder builder) throws Exception { - PostStartTrialResponse.Status status = response.getStatus(); - if (status.isTrialStarted()) { - builder.startObject() - .field("trial_was_started", true) - .field("type", startTrialRequest.getType()) - .endObject(); - } else { - builder.startObject() - .field("trial_was_started", false) - .field("error_message", status.getErrorMessage()) - .endObject(); - - } - return new BytesRestResponse(status.getRestStatus(), builder); - } - }); - } - - @Override - public String getName() { - return "xpack_upgrade_to_trial_action"; - } -} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartTrialClusterTask.java.orig b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartTrialClusterTask.java.orig deleted file mode 100644 index 3ca8dbf0eaa4e..0000000000000 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartTrialClusterTask.java.orig +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.license; - -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.message.ParameterizedMessage; -import org.elasticsearch.Version; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.ClusterStateUpdateTask; -import org.elasticsearch.cluster.metadata.MetaData; -import org.elasticsearch.common.Nullable; - -import java.time.Clock; -import java.util.UUID; - -public class StartTrialClusterTask extends ClusterStateUpdateTask { - - private final Logger logger; - private final String clusterName; - private final PostStartTrialRequest request; - private final ActionListener listener; - private final Clock clock; - - StartTrialClusterTask(Logger logger, String clusterName, Clock clock, PostStartTrialRequest request, - ActionListener listener) { - this.logger = logger; - this.clusterName = clusterName; - this.request = request; - this.listener = listener; - this.clock = clock; - } - - @Override - public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) { - LicensesMetaData oldLicensesMetaData = oldState.metaData().custom(LicensesMetaData.TYPE); - logger.debug("started self generated trial license: {}", oldLicensesMetaData); - - if (oldLicensesMetaData == null || oldLicensesMetaData.isEligibleForTrial()) { - listener.onResponse(new PostStartTrialResponse(PostStartTrialResponse.Status.UPGRADED_TO_TRIAL)); - } else { - listener.onResponse(new PostStartTrialResponse(PostStartTrialResponse.Status.TRIAL_ALREADY_ACTIVATED)); - } - } - - @Override - public ClusterState execute(ClusterState currentState) throws Exception { - LicensesMetaData currentLicensesMetaData = currentState.metaData().custom(LicensesMetaData.TYPE); - - if (currentLicensesMetaData == null || currentLicensesMetaData.isEligibleForTrial()) { - long issueDate = clock.millis(); - MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData()); - long expiryDate = issueDate + LicenseService.NON_BASIC_SELF_GENERATED_LICENSE_DURATION.getMillis(); - - License.Builder specBuilder = License.builder() - .uid(UUID.randomUUID().toString()) - .issuedTo(clusterName) - .maxNodes(LicenseService.SELF_GENERATED_LICENSE_MAX_NODES) - .issueDate(issueDate) - .type(request.getType()) - .expiryDate(expiryDate); - License selfGeneratedLicense = SelfGeneratedLicense.create(specBuilder); - LicensesMetaData newLicensesMetaData = new LicensesMetaData(selfGeneratedLicense, Version.CURRENT); - mdBuilder.putCustom(LicensesMetaData.TYPE, newLicensesMetaData); - return ClusterState.builder(currentState).metaData(mdBuilder).build(); - } else { - return currentState; - } - } - - @Override - public void onFailure(String source, @Nullable Exception e) { - logger.error(new ParameterizedMessage("unexpected failure during [{}]", source), e); - listener.onFailure(e); - } -} diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartTrialLicenseTests.java.orig b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartTrialLicenseTests.java.orig deleted file mode 100644 index d673c4e720452..0000000000000 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartTrialLicenseTests.java.orig +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.license; - -import org.elasticsearch.client.Response; -import org.elasticsearch.client.ResponseException; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.common.io.Streams; -import org.elasticsearch.common.network.NetworkModule; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.test.ESIntegTestCase; -import org.elasticsearch.transport.Netty4Plugin; -import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin; -import org.elasticsearch.xpack.core.XPackClientPlugin; - -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collection; - -import static org.elasticsearch.test.ESIntegTestCase.Scope.SUITE; - -@ESIntegTestCase.ClusterScope(scope = SUITE) -public class StartTrialLicenseTests extends AbstractLicensesIntegrationTestCase { - - @Override - protected Settings nodeSettings(int nodeOrdinal) { - return Settings.builder() - .put(super.nodeSettings(nodeOrdinal)) - .put("node.data", true) - .put(LicenseService.SELF_GENERATED_LICENSE_TYPE.getKey(), "basic") - .put(NetworkModule.HTTP_ENABLED.getKey(), true).build(); - } - - @Override - protected Collection> nodePlugins() { - return Arrays.asList(LocalStateCompositeXPackPlugin.class, Netty4Plugin.class); - } - - @Override - protected Collection> transportClientPlugins() { - return Arrays.asList(XPackClientPlugin.class, Netty4Plugin.class); - } - - public void testStartTrial() throws Exception { - LicensingClient licensingClient = new LicensingClient(client()); - ensureStartingWithBasic(); - - RestClient restClient = getRestClient(); - Response response = restClient.performRequest("GET", "/_xpack/license/trial_status"); - String body = Streams.copyToString(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)); - assertEquals(200, response.getStatusLine().getStatusCode()); - assertEquals("{\"eligible_to_start_trial\":true}", body); - - String type = randomFrom(LicenseService.VALID_TRIAL_TYPES); - - Response response2 = restClient.performRequest("POST", "/_xpack/license/start_trial?type=" + type); - String body2 = Streams.copyToString(new InputStreamReader(response2.getEntity().getContent(), StandardCharsets.UTF_8)); - assertEquals(200, response2.getStatusLine().getStatusCode()); - assertTrue(body2.contains("\"trial_was_started\":true")); - assertTrue(body2.contains("\"type\":\"" + type + "\"")); - - assertBusy(() -> { - GetLicenseResponse postTrialLicenseResponse = licensingClient.prepareGetLicense().get(); - assertEquals(type, postTrialLicenseResponse.license().type()); - }); - - Response response3 = restClient.performRequest("GET", "/_xpack/license/trial_status"); - String body3 = Streams.copyToString(new InputStreamReader(response3.getEntity().getContent(), StandardCharsets.UTF_8)); - assertEquals(200, response3.getStatusLine().getStatusCode()); - assertEquals("{\"eligible_to_start_trial\":false}", body3); - - String secondAttemptType = randomFrom(LicenseService.VALID_TRIAL_TYPES); - - ResponseException ex = expectThrows(ResponseException.class, - () -> restClient.performRequest("POST", "/_xpack/license/start_trial?type=" + secondAttemptType)); - Response response4 = ex.getResponse(); - String body4 = Streams.copyToString(new InputStreamReader(response4.getEntity().getContent(), StandardCharsets.UTF_8)); - assertEquals(403, response4.getStatusLine().getStatusCode()); - assertTrue(body4.contains("\"trial_was_started\":false")); - assertTrue(body4.contains("\"error_message\":\"Operation failed: Trial was already activated.\"")); - } - - public void testInvalidType() throws Exception { - ensureStartingWithBasic(); - - ResponseException ex = expectThrows(ResponseException.class, () -> - getRestClient().performRequest("POST", "/_xpack/license/start_trial?type=basic")); - Response response = ex.getResponse(); - String body = Streams.copyToString(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)); - assertEquals(400, response.getStatusLine().getStatusCode()); - assertTrue(body.contains("\"type\":\"illegal_argument_exception\"")); - assertTrue(body.contains("\"reason\":\"Cannot start trial of type [basic]. Valid trial types are [")); - } - - private void ensureStartingWithBasic() throws Exception { - LicensingClient licensingClient = new LicensingClient(client()); - GetLicenseResponse getLicenseResponse = licensingClient.prepareGetLicense().get(); - - if ("basic".equals(getLicenseResponse.license().type()) == false) { - licensingClient.preparePostStartBasic().setAcknowledge(true).get(); - } - - assertBusy(() -> { - GetLicenseResponse postTrialLicenseResponse = licensingClient.prepareGetLicense().get(); - assertEquals("basic", postTrialLicenseResponse.license().type()); - }); - } -} From d92138b8853dc448870ad79141f26131add4ffe6 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Wed, 25 Apr 2018 12:23:08 -0600 Subject: [PATCH 3/3] Fix version --- .../java/org/elasticsearch/license/PostStartTrialResponse.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java index efe4ae1754e80..25f354d7765a1 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/PostStartTrialResponse.java @@ -76,7 +76,8 @@ public Status getStatus() { @Override public void readFrom(StreamInput in) throws IOException { status = in.readEnum(Status.class); - if (in.getVersion().onOrAfter(Version.V_6_3_0)) { + // TODO: Change to 6.3 after backport + if (in.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { acknowledgeMessage = in.readOptionalString(); int size = in.readVInt(); Map acknowledgeMessages = new HashMap<>(size);