Moved CloudSettingId class and tests to Java

(cherry picked from commit 2545fa45ba)
This commit is contained in:
andsel 2020-11-11 13:56:55 +01:00 committed by J.A.R.V.I.S. - an Elastic git bot
parent cf7e2e308e
commit b1e5c4f257
5 changed files with 392 additions and 308 deletions

View file

@ -17,89 +17,6 @@
require "base64"
module LogStash module Util class CloudSettingId
def self.cloud_id_encode(*args)
Base64.urlsafe_encode64(args.join("$"))
end
DOT_SEPARATOR = "."
CLOUD_PORT = "443"
attr_reader :original, :decoded, :label
attr_reader :elasticsearch_host, :elasticsearch_scheme, :elasticsearch_port
attr_reader :kibana_host, :kibana_scheme, :kibana_port
attr_reader :other_identifiers
# The constructor is expecting a 'cloud.id', a string in 2 variants.
# 1 part example: 'dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRub3RhcmVhbCRpZGVudGlmaWVy'
# 2 part example: 'foobar:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRub3RhcmVhbCRpZGVudGlmaWVy'
# The two part variant has a 'label' prepended with a colon separator. The label is not encoded.
# The 1 part (or second section of the 2 part variant) is base64 encoded.
# The original string before encoding has three segments separated by a dollar sign.
# e.g. 'us-east-1.aws.found.io$notareal$identifier'
# The first segment is the cloud base url, e.g. 'us-east-1.aws.found.io'
# The second segment is the elasticsearch host identifier, e.g. 'notareal'
# The third segment is the kibana host identifier, e.g. 'identifier'
# The 'cloud.id' value decoded into the #attr_reader ivars.
def initialize(value)
return if value.nil?
unless value.is_a?(String)
raise ArgumentError.new("Cloud Id must be String. Received: #{value.class}")
end
@original = value
@label, colon, encoded = @original.partition(":")
if encoded.empty?
@decoded = Base64.urlsafe_decode64(@label) rescue ""
@label = ""
else
@decoded = Base64.urlsafe_decode64(encoded) rescue ""
end
@decoded = @decoded.encode(Encoding::UTF_8, :invalid => :replace, :undef => :replace)
if @decoded.count("$") < 2
raise ArgumentError.new("Cloud Id, after decoding, is invalid. Format: '<segment1>$<segment2>$<segment3>'. Received: \"#{@decoded}\".")
end
segments = @decoded.split("$")
if segments.any?(&:empty?)
raise ArgumentError.new("Cloud Id, after decoding, is invalid. Format: '<segment1>$<segment2>$<segment3>'. Received: \"#{@decoded}\".")
end
cloud_base = segments.shift
cloud_host = "#{DOT_SEPARATOR}#{cloud_base}"
cloud_host, cloud_port = cloud_host.split(":")
cloud_port ||= CLOUD_PORT
@elasticsearch_host, @kibana_host, *@other_identifiers = segments
@elasticsearch_host, @elasticsearch_port = @elasticsearch_host.split(":")
@kibana_host, @kibana_port = @kibana_host.split(":") if @kibana_host
@elasticsearch_port ||= cloud_port
@kibana_port ||= cloud_port
@other_identifiers ||= []
if @elasticsearch_host == "undefined"
raise ArgumentError.new("Cloud Id, after decoding, elasticsearch segment is 'undefined', literally.")
end
@elasticsearch_scheme = "https"
@elasticsearch_host.concat(cloud_host)
@elasticsearch_host.concat(":#{@elasticsearch_port}")
if @kibana_host == "undefined"
raise ArgumentError.new("Cloud Id, after decoding, the kibana segment is 'undefined', literally. You may need to enable Kibana in the Cloud UI.")
end
@kibana_scheme = "https"
@kibana_host ||= String.new # non-sense really to have '.my-host:443' but we're mirroring others
@kibana_host.concat(cloud_host)
@kibana_host.concat(":#{@kibana_port}")
end
def to_s
@decoded.to_s
end
def inspect
to_s
end
end end end
module LogStash; module Util
java_import org.logstash.util.CloudSettingId
end; end

View file

@ -50,26 +50,26 @@ describe LogStash::Setting::Modules do
subject { described_class.new("mycloudid", LogStash::Util::CloudSettingId) }
context "when given a string which is not a cloud id" do
it "should raise an exception" do
expect { subject.set("foobarbaz") }.to raise_error(ArgumentError, /Cloud Id.*is invalid/)
expect { subject.set("foobarbaz") }.to raise_error(IllegalArgumentException, /Cloud Id.*is invalid/)
end
end
context "when given a string which is empty" do
it "should raise an exception" do
expect { subject.set("") }.to raise_error(ArgumentError, /Cloud Id.*is invalid/)
expect { subject.set("") }.to raise_error(IllegalArgumentException, /Cloud Id.*is invalid/)
end
end
context "when given a string which is has environment prefix only" do
it "should raise an exception" do
expect { subject.set("testing:") }.to raise_error(ArgumentError, /Cloud Id.*is invalid/)
expect { subject.set("testing:") }.to raise_error(IllegalArgumentException, /Cloud Id.*is invalid/)
end
end
context "when given a badly formatted encoded id" do
it "should not raise an error" do
encoded = Base64.urlsafe_encode64("foo$$bal")
expect { subject.set(encoded) }.to raise_error(ArgumentError, "Cloud Id, after decoding, is invalid. Format: '<segment1>$<segment2>$<segment3>'. Received: \"foo$$bal\".")
expect { subject.set(encoded) }.to raise_error(IllegalArgumentException, "Cloud Id, after decoding, is invalid. Format: '<segment1>$<segment2>$<segment3>'. Received: \"foo$$bal\".")
end
end

View file

@ -1,218 +0,0 @@
# Licensed to Elasticsearch B.V. under one or more contributor
# license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright
# ownership. Elasticsearch B.V. licenses this file to you under
# the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
require "spec_helper"
require "logstash/util/cloud_setting_id"
describe LogStash::Util::CloudSettingId do
let(:input) { "foobar:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRub3RhcmVhbCRpZGVudGlmaWVy" }
subject { described_class.new(input) }
describe "when given unacceptable input" do
it "a nil input does not raise an exception" do
expect{described_class.new(nil)}.not_to raise_exception
end
it "when given a nil input, the accessors are all nil" do
cloud_id = described_class.new(nil)
expect(cloud_id.original).to be_nil
expect(cloud_id.decoded).to be_nil
expect(cloud_id.label).to be_nil
expect(cloud_id.elasticsearch_host).to be_nil
expect(cloud_id.kibana_host).to be_nil
expect(cloud_id.elasticsearch_scheme).to be_nil
expect(cloud_id.kibana_scheme).to be_nil
end
context "when a malformed value is given" do
let(:raw) {%w(first second)}
let(:input) { described_class.cloud_id_encode(*raw) }
it "raises an error" do
expect{subject}.to raise_exception(ArgumentError, "Cloud Id, after decoding, is invalid. Format: '<segment1>$<segment2>$<segment3>'. Received: \"#{raw[0]}$#{raw[1]}\".")
end
end
context "when at least one segment is empty" do
let(:raw) {["first", "", "third"]}
let(:input) { described_class.cloud_id_encode(*raw) }
it "raises an error" do
expect{subject}.to raise_exception(ArgumentError, "Cloud Id, after decoding, is invalid. Format: '<segment1>$<segment2>$<segment3>'. Received: \"#{raw[0]}$#{raw[1]}$#{raw[2]}\".")
end
end
context "when elasticsearch segment is undefined" do
let(:raw) {%w(us-east-1.aws.found.io undefined my-kibana)}
let(:input) { described_class.cloud_id_encode(*raw) }
it "raises an error" do
expect{subject}.to raise_exception(ArgumentError, "Cloud Id, after decoding, elasticsearch segment is 'undefined', literally.")
end
end
context "when kibana segment is undefined" do
let(:raw) {%w(us-east-1.aws.found.io my-elastic-cluster undefined)}
let(:input) { described_class.cloud_id_encode(*raw) }
it "raises an error" do
expect{subject}.to raise_exception(ArgumentError, "Cloud Id, after decoding, the kibana segment is 'undefined', literally. You may need to enable Kibana in the Cloud UI.")
end
end
end
describe "without a label" do
let(:input) { "dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRub3RhcmVhbCRpZGVudGlmaWVy" }
it "#label is empty" do
expect(subject.label).to be_empty
end
it "#decode is set" do
expect(subject.decoded).to eq("us-east-1.aws.found.io$notareal$identifier")
end
end
describe "when given acceptable input, the accessors:" do
it '#original has a value' do
expect(subject.original).to eq(input)
end
it '#decoded has a value' do
expect(subject.decoded).to eq("us-east-1.aws.found.io$notareal$identifier")
end
it '#label has a value' do
expect(subject.label).to eq("foobar")
end
it '#elasticsearch_host has a value' do
expect(subject.elasticsearch_host).to eq("notareal.us-east-1.aws.found.io:443")
end
it '#elasticsearch_scheme has a value' do
expect(subject.elasticsearch_scheme).to eq("https")
end
it '#kibana_host has a value' do
expect(subject.kibana_host).to eq("identifier.us-east-1.aws.found.io:443")
end
it '#kibana_scheme has a value' do
expect(subject.kibana_scheme).to eq("https")
end
it '#to_s has a value of #decoded' do
expect(subject.to_s).to eq(subject.decoded)
end
end
context "when cloud id contains port descriptions for ES and Kibana" do
let(:input) { "different-es-kb-port:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJGFjMzFlYmI5MDI0MTc3MzE1NzA0M2MzNGZkMjZmZDQ2OjkyNDMkYTRjMDYyMzBlNDhjOGZjZTdiZTg4YTA3NGEzYmIzZTA6OTI0NA==" }
it "decodes the elasticsearch port corretly" do
expect(subject.elasticsearch_host).to eq("ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:9243")
end
it "decodes the kibana port corretly" do
expect(subject.kibana_host).to eq("a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9244")
end
end
context "when cloud id contains cloud port" do
let(:input) { "custom-port:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvOjkyNDMkYWMzMWViYjkwMjQxNzczMTU3MDQzYzM0ZmQyNmZkNDYkYTRjMDYyMzBlNDhjOGZjZTdiZTg4YTA3NGEzYmIzZTA=" }
it "decodes the elasticsearch port corretly" do
expect(subject.elasticsearch_host).to eq("ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:9243")
end
it "decodes the kibana port corretly" do
expect(subject.kibana_host).to eq("a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9243")
end
end
context "when cloud id only defines kibana port" do
let(:input) { "only-kb-set:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJGFjMzFlYmI5MDI0MTc3MzE1NzA0M2MzNGZkMjZmZDQ2JGE0YzA2MjMwZTQ4YzhmY2U3YmU4OGEwNzRhM2JiM2UwOjkyNDQ=" }
it "defaults the elasticsearch port to 443" do
expect(subject.elasticsearch_host).to eq("ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:443")
end
it "decodes the kibana port corretly" do
expect(subject.kibana_host).to eq("a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9244")
end
end
context "when cloud id defines cloud port and kibana port" do
let(:input) { "host-and-kb-set:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvOjkyNDMkYWMzMWViYjkwMjQxNzczMTU3MDQzYzM0ZmQyNmZkNDYkYTRjMDYyMzBlNDhjOGZjZTdiZTg4YTA3NGEzYmIzZTA6OTI0NA==" }
it "sets the elasticsearch port to cloud port" do
expect(subject.elasticsearch_host).to eq("ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:9243")
end
it "overrides cloud port with the kibana port" do
expect(subject.kibana_host).to eq("a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9244")
end
end
context "when cloud id defines extra data" do
let(:input) { "extra-items:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJGFjMzFlYmI5MDI0MTc3MzE1NzA0M2MzNGZkMjZmZDQ2JGE0YzA2MjMwZTQ4YzhmY2U3YmU4OGEwNzRhM2JiM2UwJGFub3RoZXJpZCRhbmRhbm90aGVy" }
it "captures the elasticsearch host" do
expect(subject.elasticsearch_host).to eq("ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:443")
end
it "captures the kibana host" do
expect(subject.kibana_host).to eq("a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:443")
end
it "captures the remaining identifiers" do
expect(subject.other_identifiers).to eq(["anotherid", "andanother"])
end
end
describe "when given acceptable input (with empty kibana uuid), the accessors:" do
let(:input) { "a-test:ZWNlLmhvbWUubGFuJHRlc3Qk" } # ece.home.lan$test$
it '#original has a value' do
expect(subject.original).to eq(input)
end
it '#decoded has a value' do
expect(subject.decoded).to eq("ece.home.lan$test$")
end
it '#label has a value' do
expect(subject.label).to eq("a-test")
end
it '#elasticsearch_host has a value' do
expect(subject.elasticsearch_host).to eq("test.ece.home.lan:443")
end
it '#elasticsearch_scheme has a value' do
expect(subject.elasticsearch_scheme).to eq("https")
end
it '#kibana_host has a value' do
# NOTE: kibana part is not relevant -> this is how python/beats(go) code behaves
expect(subject.kibana_host).to eq(".ece.home.lan:443")
end
it '#kibana_scheme has a value' do
expect(subject.kibana_scheme).to eq("https")
end
it '#to_s has a value of #decoded' do
expect(subject.to_s).to eq(subject.decoded)
end
end
describe "a lengthy real-world input, the accessors:" do
let(:input) do
"ZWFzdHVzMi5henVyZS5lbGFzdGljLWNsb3VkLmNvbTo5MjQzJDQwYjM0MzExNmNmYTRlYmNiNzZjMTFlZTIzMjlmOTJkJDQzZDA5MjUyNTAyYzQxODlhMzc2ZmQwY2YyY2QwODQ4"
# eastus2.azure.elastic-cloud.com:9243$40b343116cfa4ebcb76c11ee2329f92d$43d09252502c4189a376fd0cf2cd0848
end
it '#original has a value' do
expect(subject.original).to eq(input)
end
it '#decoded has a value' do
expect(subject.decoded).to eq("eastus2.azure.elastic-cloud.com:9243$40b343116cfa4ebcb76c11ee2329f92d$43d09252502c4189a376fd0cf2cd0848")
end
it '#label has a value' do
expect(subject.label).to eq("")
end
it '#elasticsearch_host has a value' do
expect(subject.elasticsearch_host).to eq("40b343116cfa4ebcb76c11ee2329f92d.eastus2.azure.elastic-cloud.com:9243")
end
it '#kibana_host has a value' do
expect(subject.kibana_host).to eq("43d09252502c4189a376fd0cf2cd0848.eastus2.azure.elastic-cloud.com:9243")
end
it '#to_s has a value of #decoded' do
expect(subject.to_s).to eq(subject.decoded)
end
end
end

View file

@ -0,0 +1,191 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.logstash.util;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
/*
* The constructor is expecting a 'cloud.id', a string in 2 variants.
* 1 part example: 'dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRub3RhcmVhbCRpZGVudGlmaWVy'
* 2 part example: 'foobar:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRub3RhcmVhbCRpZGVudGlmaWVy'
* The two part variant has a 'label' prepended with a colon separator. The label is not encoded.
* The 1 part (or second section of the 2 part variant) is base64 encoded.
* The original string before encoding has three segments separated by a dollar sign.
* e.g. 'us-east-1.aws.found.io$notareal$identifier'
* The first segment is the cloud base url, e.g. 'us-east-1.aws.found.io'
* The second segment is the elasticsearch host identifier, e.g. 'notareal'
* The third segment is the kibana host identifier, e.g. 'identifier'
* The 'cloud.id' value decoded into the various fields.
*/
public class CloudSettingId {
private static class HostAndPort {
static final HostAndPort NO_HOST = new HostAndPort("", null);
private final String host;
private final String port;
private HostAndPort(String host, String port) {
this.host = host;
this.port = port;
}
String portOrDefault(String defaultPort) {
return port == null ? defaultPort : port;
}
static HostAndPort parseHostAndPort(String part, String guidanceMessageWhenHostEqualsUndefined) {
final String[] hostParts = part.split(":");
String host = hostParts[0];
if ("undefined".equals(host)) {
throw new IllegalArgumentException(guidanceMessageWhenHostEqualsUndefined);
}
String port = null;
if (hostParts.length > 1) {
port = hostParts[1];
}
return new HostAndPort(host, port);
}
}
public static final String DOT_SEPARATOR = ".";
public static final String CLOUD_PORT = "443";
private String original;
private String decoded;
private String label;
private String elasticsearchScheme;
private String elasticsearchHost;
private String elasticsearchPort;
private String kibanaScheme;
private String kibanaHost;
private String kibanaPort;
private String[] otherIdentifiers = new String[0];
public CloudSettingId(String value) {
if (value == null) {
return;
}
original = value;
final String[] parts = original.split(":");
label = parts[0];
String encoded = null;
if (parts.length > 1) {
encoded = parts[1];
}
if (encoded == null || encoded.isEmpty()) {
try {
decoded = new String(Base64.getUrlDecoder().decode(label), StandardCharsets.UTF_8);
} catch (IllegalArgumentException iaex) {
decoded = "";
}
label = "";
} else {
try {
decoded = new String(Base64.getUrlDecoder().decode(encoded), StandardCharsets.UTF_8);
} catch (IllegalArgumentException iaex) {
decoded = "";
}
}
long separatorCount = decoded.chars().filter(c -> c == '$').count();
if (separatorCount < 2) {
throw new IllegalArgumentException("Cloud Id, after decoding, is invalid. Format: '<segment1>$<segment2>$<segment3>'. Received: \"" + decoded + "\".");
}
final String[] segments = decoded.split("\\$");
if (Arrays.stream(segments).anyMatch(String::isEmpty)) {
throw new IllegalArgumentException("Cloud Id, after decoding, is invalid. Format: '<segment1>$<segment2>$<segment3>'. Received: \"" + decoded + "\".");
}
String cloudBase = segments[0];
String cloudHost = DOT_SEPARATOR + cloudBase;
final String[] hostParts = cloudHost.split(":");
final HostAndPort cloud = new HostAndPort(hostParts[0], hostParts.length > 1 ? hostParts[1] : CLOUD_PORT);
final HostAndPort elasticsearch = HostAndPort.parseHostAndPort(segments[1], "Cloud Id, after decoding, elasticsearch segment is 'undefined', literally.");
elasticsearchPort = elasticsearch.portOrDefault(cloud.port);
elasticsearchHost = elasticsearch.host + cloud.host + ":" + elasticsearchPort;
elasticsearchScheme = "https";
final HostAndPort kibana;
if (segments.length > 2) {
kibana = HostAndPort.parseHostAndPort(segments[2], "Cloud Id, after decoding, the kibana segment is 'undefined', literally. You may need to enable Kibana in the Cloud UI.");
} else {
// non-sense really to have '.my-host:443' but we're mirroring others
kibana = HostAndPort.NO_HOST;
}
kibanaPort = kibana.portOrDefault(cloud.port);
kibanaHost = kibana.host + cloud.host + ":" + kibanaPort;
kibanaScheme = "https";
if (segments.length > 3) {
otherIdentifiers = Arrays.copyOfRange(segments, 3, segments.length);
}
}
public String getOriginal() {
return original;
}
public String getDecoded() {
return decoded;
}
public String getLabel() {
return label;
}
public String getElasticsearchScheme() {
return elasticsearchScheme;
}
public String getElasticsearchHost() {
return elasticsearchHost;
}
public String getElasticsearchPort() {
return elasticsearchPort;
}
public String getKibanaScheme() {
return kibanaScheme;
}
public String getKibanaHost() {
return kibanaHost;
}
public String getKibanaPort() {
return kibanaPort;
}
public String[] getOtherIdentifiers() {
return otherIdentifiers;
}
@Override
public String toString() {
return decoded;
}
public static String cloudIdEncode(String... args) {
final String joinedArgs = String.join("$", args);
return Base64.getUrlEncoder().encodeToString(joinedArgs.getBytes());
}
}

View file

@ -0,0 +1,194 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.logstash.util;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.junit.Assert.*;
public class CloudSettingIdTest {
private String input = "foobar:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRub3RhcmVhbCRpZGVudGlmaWVy";
private CloudSettingId sut;
@Rule
public ExpectedException exceptionRule = ExpectedException.none();
@Before
public void setUp() {
sut = new CloudSettingId(input);
}
// when given unacceptable input
@Test
public void testNullInputDoenstThrowAnException() {
new CloudSettingId(null);
}
@Test
public void testNullInputMakesAllGettersReturnNull() {
sut = new CloudSettingId(null);
assertNull(sut.getOriginal());
assertNull(sut.getDecoded());
assertNull(sut.getLabel());
assertNull(sut.getElasticsearchHost());
assertNull(sut.getKibanaHost());
assertNull(sut.getElasticsearchScheme());
assertNull(sut.getKibanaScheme());
}
@Test
public void testThrowExceptionWhenMalformedValueIsGiven() {
String[] raw = new String[] {"first", "second"};
String encoded = CloudSettingId.cloudIdEncode(raw);
exceptionRule.expect(IllegalArgumentException.class);
exceptionRule.expectMessage("Cloud Id, after decoding, is invalid. Format: '<segment1>$<segment2>$<segment3>'. Received: \"" + String.join("$", raw) + "\".");
new CloudSettingId(encoded);
}
@Test
public void testThrowExceptionWhenAtLeatOneSegmentIsEmpty() {
String[] raw = new String[] {"first", "", "third"};
String encoded = CloudSettingId.cloudIdEncode(raw);
exceptionRule.expect(IllegalArgumentException.class);
exceptionRule.expectMessage("Cloud Id, after decoding, is invalid. Format: '<segment1>$<segment2>$<segment3>'. Received: \"" + String.join("$", raw) + "\".");
new CloudSettingId(encoded);
}
@Test
public void testThrowExceptionWhenElasticSegmentSegmentIsUndefined() {
String[] raw = new String[] {"us-east-1.aws.found.io", "undefined", "my-kibana"};
String encoded = CloudSettingId.cloudIdEncode(raw);
exceptionRule.expect(IllegalArgumentException.class);
exceptionRule.expectMessage("Cloud Id, after decoding, elasticsearch segment is 'undefined', literally.");
new CloudSettingId(encoded);
}
@Test
public void testThrowExceptionWhenKibanaSegmentSegmentIsUndefined() {
String[] raw = new String[] {"us-east-1.aws.found.io", "my-elastic-cluster", "undefined"};
String encoded = CloudSettingId.cloudIdEncode(raw);
exceptionRule.expect(IllegalArgumentException.class);
exceptionRule.expectMessage("Cloud Id, after decoding, the kibana segment is 'undefined', literally. You may need to enable Kibana in the Cloud UI.");
new CloudSettingId(encoded);
}
// without a label
@Test
public void testDecodingWithoutLabelSegment() {
sut = new CloudSettingId("dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRub3RhcmVhbCRpZGVudGlmaWVy");
assertEquals("#label is empty", "", sut.getLabel());
assertEquals("#decode is set", "us-east-1.aws.found.io$notareal$identifier", sut.getDecoded());
}
// when given acceptable input, the accessors:
@Test
public void testAccessorsWithAcceptableInput() {
assertEquals("#original has a value", input, sut.getOriginal());
assertEquals("#decoded has a value", "us-east-1.aws.found.io$notareal$identifier", sut.getDecoded());
assertEquals("#label has a value", "foobar", sut.getLabel());
assertEquals("#elasticsearch_host has a value", "notareal.us-east-1.aws.found.io:443", sut.getElasticsearchHost());
assertEquals("#elasticsearch_scheme has a value", "https", sut.getElasticsearchScheme());
assertEquals("#kibana_host has a value", "identifier.us-east-1.aws.found.io:443", sut.getKibanaHost());
assertEquals("#kibana_scheme has a value", "https", sut.getKibanaScheme());
assertEquals("#to_s has a value of #decoded", sut.toString(), sut.getDecoded());
}
@Test
public void testWhenCloudIdContainsPortDescriptionForESAndKibana() {
sut = new CloudSettingId("different-es-kb-port:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJGFjMzFlYmI5MDI0MTc3MzE1NzA0M2MzNGZkMjZmZDQ2OjkyNDMkYTRjMDYyMzBlNDhjOGZjZTdiZTg4YTA3NGEzYmIzZTA6OTI0NA==");
assertEquals("decodes the elasticsearch port corretly", "ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:9243", sut.getElasticsearchHost());
assertEquals("decodes the kibana port corretly", "a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9244", sut.getKibanaHost());
}
@Test
public void testWhenCloudIdContainsCloudPort() {
sut = new CloudSettingId("custom-port:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvOjkyNDMkYWMzMWViYjkwMjQxNzczMTU3MDQzYzM0ZmQyNmZkNDYkYTRjMDYyMzBlNDhjOGZjZTdiZTg4YTA3NGEzYmIzZTA=");
assertEquals("decodes the elasticsearch port corretly", "ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:9243", sut.getElasticsearchHost());
assertEquals("decodes the kibana port corretly", "a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9243", sut.getKibanaHost());
}
@Test
public void testWhenCloudIdOnlyDefinesKibanaPort() {
sut = new CloudSettingId("only-kb-set:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJGFjMzFlYmI5MDI0MTc3MzE1NzA0M2MzNGZkMjZmZDQ2JGE0YzA2MjMwZTQ4YzhmY2U3YmU4OGEwNzRhM2JiM2UwOjkyNDQ=");
assertEquals("defaults the elasticsearch port to 443", "ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:443", sut.getElasticsearchHost());
assertEquals("decodes the kibana port corretly", "a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9244", sut.getKibanaHost());
}
@Test
public void testWhenCloudIdDefinesCloudPortAndKibanaPort() {
sut = new CloudSettingId("host-and-kb-set:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvOjkyNDMkYWMzMWViYjkwMjQxNzczMTU3MDQzYzM0ZmQyNmZkNDYkYTRjMDYyMzBlNDhjOGZjZTdiZTg4YTA3NGEzYmIzZTA6OTI0NA==");
assertEquals("sets the elasticsearch port to cloud port", "ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:9243", sut.getElasticsearchHost());
assertEquals("overrides cloud port with the kibana port", "a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9244", sut.getKibanaHost());
}
@Test
public void testWhenCloudIdDefinesExtraData() {
sut = new CloudSettingId("extra-items:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJGFjMzFlYmI5MDI0MTc3MzE1NzA0M2MzNGZkMjZmZDQ2JGE0YzA2MjMwZTQ4YzhmY2U3YmU4OGEwNzRhM2JiM2UwJGFub3RoZXJpZCRhbmRhbm90aGVy");
assertEquals("captures the elasticsearch host", "ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:443", sut.getElasticsearchHost());
assertEquals("captures the kibana host", "a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:443", sut.getKibanaHost());
assertArrayEquals("captures the remaining identifiers", new String[] {"anotherid", "andanother"}, sut.getOtherIdentifiers());
}
// when given acceptable input (with empty kibana uuid), the accessors:
@Test
public void testGivenAcceptableInputEmptyKibanaUUID() {
input = "a-test:ZWNlLmhvbWUubGFuJHRlc3Qk";
sut = new CloudSettingId(input); // ece.home.lan$test$
assertEquals("#original has a value", input, sut.getOriginal());
assertEquals("#decoded has a value", "ece.home.lan$test$", sut.getDecoded());
assertEquals("#label has a value", "a-test", sut.getLabel());
assertEquals("#elasticsearch_host has a value", "test.ece.home.lan:443", sut.getElasticsearchHost());
assertEquals("#elasticsearch_scheme has a value", "https", sut.getElasticsearchScheme());
// NOTE: kibana part is not relevant -> this is how python/beats(go) code behaves
assertEquals("#kibana_host has a value", ".ece.home.lan:443", sut.getKibanaHost());
assertEquals("#kibana_scheme has a value", "https", sut.getKibanaScheme());
assertEquals("#toString has a value of #decoded", sut.getDecoded(), sut.toString());
}
// a lengthy real-world input, the accessors:
@Test
public void testWithRealWorldInput() {
//eastus2.azure.elastic-cloud.com:9243$40b343116cfa4ebcb76c11ee2329f92d$43d09252502c4189a376fd0cf2cd0848
input = "ZWFzdHVzMi5henVyZS5lbGFzdGljLWNsb3VkLmNvbTo5MjQzJDQwYjM0MzExNmNmYTRlYmNiNzZjMTFlZTIzMjlmOTJkJDQzZDA5MjUyNTAyYzQxODlhMzc2ZmQwY2YyY2QwODQ4";
sut = new CloudSettingId(input);
assertEquals("#original has a value", input, sut.getOriginal());
assertEquals("#decoded has a value", "eastus2.azure.elastic-cloud.com:9243$40b343116cfa4ebcb76c11ee2329f92d$43d09252502c4189a376fd0cf2cd0848", sut.getDecoded());
assertEquals("#label has a value", "", sut.getLabel());
assertEquals("#elasticsearch_host has a value", "40b343116cfa4ebcb76c11ee2329f92d.eastus2.azure.elastic-cloud.com:9243", sut.getElasticsearchHost());
assertEquals("#kibana_host has a value", "43d09252502c4189a376fd0cf2cd0848.eastus2.azure.elastic-cloud.com:9243", sut.getKibanaHost());
assertEquals("#toString has a value of #decoded", sut.getDecoded(), sut.toString());
}
}