/*
* Copyright 2011 Splunk, Inc.
*
* Licensed 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 com.splunk;
import org.junit.Assert;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ServiceTest extends SDKTestCase {
private static final String QUERY = "search index=_internal | head 10";
@Test
public void testCapabilities() throws Exception {
List<String> expected = Arrays.asList(
"admin_all_objects", "change_authentication",
"change_own_password", "delete_by_keyword",
"edit_deployment_client", "edit_deployment_server",
"edit_dist_peer", "edit_forwarders", "edit_httpauths",
"edit_input_defaults", "edit_monitor", "edit_roles",
"edit_scripted", "edit_search_server", "edit_server",
"edit_splunktcp", "edit_splunktcp_ssl", "edit_tcp", "edit_udp",
"edit_user", "edit_web_settings", "get_metadata",
"get_typeahead", "indexes_edit", "license_edit", "license_tab",
"list_deployment_client", "list_forwarders", "list_httpauths",
"list_inputs", "request_remote_tok", "rest_apps_management",
"rest_apps_view", "rest_properties_get", "rest_properties_set",
"restart_splunkd", "rtsearch", "schedule_search", "search",
"use_file_operator");
String[] caps = service.getCapabilities();
for (String name : expected) {
Assert.assertTrue(contains(caps, name));
}
}
// Make a few simple requests and make sure the results look ok.
@Test
public void testGet() {
// Check a few paths that we know exist
String[] paths = {
"/",
"/services",
"/services/search/jobs",
"search/jobs",
"authentication/users"
};
for (String path : paths)
checkResponse(service.get(path));
// And make sure we get the expected 404
try {
service.get("/zippy");
Assert.fail("Expected HttpException");
}
catch (HttpException e) {
Assert.assertEquals(404, e.getStatus());
}
}
@Test
public void testInfo() throws Exception {
List <String> expected = Arrays.asList(
"build", "cpu_arch", "guid", "isFree", "isTrial", "licenseKeys",
"licenseSignature", "licenseState", "master_guid", "mode",
"os_build", "os_name", "os_version", "serverName", "version");
ServiceInfo info = service.getInfo();
for (String name : expected)
Assert.assertTrue(info.containsKey(name));
info.getBuild();
info.getCpuArch();
info.getGuid();
info.getLicenseKeys();
info.getLicenseLabels();
info.getLicenseSignature();
info.getLicenseState();
info.getMasterGuid();
info.getMode();
info.getOsBuild();
info.getOsName();
info.getOsVersion();
info.getServerName();
info.getVersion();
info.isFree();
info.isRtSearchEnabled();
info.isTrial();
Assert.assertEquals(info.getService(), service);
}
private void checkLoggedIn(Service service) {
ResponseMessage response;
response = service.get("/services/authentication/users");
checkResponse(response);
}
protected void checkNotLoggedIn(Service service) {
try {
service.get("/services/authentication/users");
Assert.fail("Expected HttpException");
}
catch (HttpException e) {
Assert.assertEquals(401, e.getStatus());
}
}
@Test
public void testLogin() {
Service service = new Service(
(String) command.opts.get("host"),
(Integer) command.opts.get("port"),
(String) command.opts.get("scheme"));
// Not logged in, should fail with 401
checkNotLoggedIn(service);
// Logged in, request should succeed
service.login(
(String) command.opts.get("username"),
(String) command.opts.get("password"));
checkLoggedIn(service);
// Logout, the request should fail with a 401
service.logout();
checkNotLoggedIn(service);
}
@Test
public void testLoginWithoutArguments() {
ServiceArgs args = new ServiceArgs();
args.setHost((String) command.opts.get("host"));
args.setPort((Integer) command.opts.get("port"));
args.setScheme((String) command.opts.get("scheme"));
args.setUsername((String) command.opts.get("username"));
args.setPassword((String) command.opts.get("password"));
Service service = new Service(args);
checkNotLoggedIn(service);
service.login();
checkLoggedIn(service);
service.logout();
checkNotLoggedIn(service);
}
@Test
public void testLoginWithArgumentsOverridesServiceArgs() {
ServiceArgs args = new ServiceArgs();
args.setHost((String) command.opts.get("host"));
args.setPort((Integer) command.opts.get("port"));
args.setScheme((String) command.opts.get("scheme"));
args.setUsername("I can't possibly be a user");
args.setPassword("This password is nonsense.");
Service service = new Service(args);
checkNotLoggedIn(service);
service.login(
(String) command.opts.get("username"),
(String) command.opts.get("password")
);
checkLoggedIn(service);
service.logout();
checkNotLoggedIn(service);
}
@Test(expected=IllegalStateException.class)
public void testLoginWithoutAnyUsernameFails() {
ServiceArgs args = new ServiceArgs();
args.setHost((String) command.opts.get("host"));
args.setPort((Integer) command.opts.get("port"));
args.setScheme((String) command.opts.get("scheme"));
Service service = new Service(args);
service.login();
}
@Test
public void testLoginWithToken() {
String validToken = service.getToken();
Assert.assertTrue(validToken.startsWith("Splunk "));
Service s = new Service(service.getHost(), service.getPort());
s.setToken(validToken);
// Ensure we can perform some action.
// In particular we don't expect an unauthenticated error.
s.getSettings().refresh();
// Make sure we're still using the same token.
// In particular we don't want to trigger auto-login functionality
// that gets a new token.
Assert.assertEquals(s.getToken(), validToken);
}
@Test
public void testLoginGetters() {
Service s = new Service("theHost");
try {
s.login("theUser", "thePassword");
} catch (Exception e) {
// Don't care if login fails. It probably will.
}
Assert.assertEquals("theUser", s.getUsername());
Assert.assertEquals("thePassword", s.getPassword());
}
@Test
public void testJobs() throws InterruptedException {
JobCollection jobs = service.getJobs();
for (Job entity : jobs.values())
testGetters(entity);
Job job = jobs.create("search * | head 1");
while (!job.isDone()) {
Thread.sleep(500);
}
testGetters(job);
job.cancel();
}
// Perform some non-intrusive inspection of the given Job object.
private void testGetters(Job job) {
ready(job);
job.getDelegate();
job.getDiskUsage();
job.getDispatchState();
job.getDoneProgress();
job.getDropCount();
job.getEarliestTime();
job.getEventAvailableCount();
job.getEventCount();
job.getEventFieldCount();
job.getEventIsStreaming();
job.getEventIsTruncated();
job.getEventSearch();
job.getEventSorting();
job.getKeywords();
job.getLabel();
job.getLatestTime();
job.getNumPreviews();
job.getPriority();
job.getRemoteSearch();
job.getReportSearch();
job.getResultCount();
job.getResultIsStreaming();
job.getResultPreviewCount();
job.getRunDuration();
job.getScanCount();
job.getSearch();
job.getSearchEarliestTime();
job.getSearchLatestTime();
job.getSid();
job.getStatusBuckets();
job.getTtl();
job.isDone();
job.isFailed();
job.isFinalized();
job.isPaused();
job.isPreviewEnabled();
job.isRealTimeSearch();
job.isSaved();
job.isSavedSearch();
job.isZombie();
Assert.assertEquals(job.getName(), job.getSid());
}
@Test
public void testSettersAndGettersPattern() {
Settings settings = service.getSettings();
// Save
String originalHost = settings.getHost();
int originalMinSpace = settings.getMinFreeSpace();
// Ensure setter updates local state
settings.setHost("sdk-host");
Assert.assertEquals("sdk-host", settings.getHost());
// Ensure update() merges arguments with local state
settings.setHost("sdk-host2");
settings.update(Args.create("minFreeSpace", 500));
Assert.assertEquals("sdk-host2", settings.getHost());
Assert.assertEquals(500, settings.getMinFreeSpace());
// Ensure update argument takes precedence over local state
settings.setMinimumFreeSpace(600);
settings.update(Args.create("minFreeSpace", 700));
Assert.assertEquals(700, settings.getMinFreeSpace());
// Restore
{
settings.setHost(originalHost);
settings.setMinimumFreeSpace(originalMinSpace);
settings.update();
Assert.assertEquals(settings.getMinFreeSpace(),
originalMinSpace);
Assert.assertEquals(settings.getHost(), originalHost);
}
// Twiddling the host value makes Splunk want to restart.
// No actual instability results, though.
clearRestartMessage();
}
@Test
public void testUsers() {
Args args;
User user;
String username = "sdk-user";
String password = "changeme!";
UserCollection users = service.getUsers();
// Cleanup potential prior failed test run.
users.remove(username);
Assert.assertFalse(users.containsKey(username));
// Create user using base create method
{
args = new Args();
args.put("password", password);
args.put("roles", "power");
user = users.create(username, args);
Assert.assertTrue(users.containsKey(username));
Assert.assertEquals(username, user.getName());
Assert.assertEquals(1, user.getRoles().length);
Assert.assertTrue(contains(user.getRoles(), "power"));
users.remove(username);
Assert.assertFalse(users.containsKey(username));
}
// Create user using derived create method
{
user = users.create(username, password, "power");
Assert.assertTrue(users.containsKey(username));
Assert.assertEquals(username, user.getName());
Assert.assertEquals(1, user.getRoles().length);
Assert.assertTrue(contains(user.getRoles(), "power"));
users.remove(username);
Assert.assertFalse(users.containsKey(username));
}
// Create using derived method with multiple roles
{
user = users.create(
username, password, new String[] { "power", "user" });
Assert.assertTrue(users.containsKey(username));
Assert.assertEquals(username, user.getName());
Assert.assertEquals(2, user.getRoles().length);
Assert.assertTrue(contains(user.getRoles(), "power"));
Assert.assertTrue(contains(user.getRoles(), "user"));
users.remove(username);
Assert.assertFalse(users.containsKey(username));
}
// Create using derived method with multiple roles and extra properties
{
args = new Args();
args.put("realname", "Renzo");
args.put("email", "email.me@now.com");
args.put("defaultApp", "search");
user = users.create(
username, password, new String[] { "power", "user" }, args);
Assert.assertTrue(users.containsKey(username));
Assert.assertEquals(username, user.getName());
Assert.assertEquals(2, user.getRoles().length);
Assert.assertTrue(contains(user.getRoles(), "power"));
Assert.assertTrue(contains(user.getRoles(), "user"));
Assert.assertEquals("Renzo", user.getRealName());
Assert.assertEquals("email.me@now.com", user.getEmail());
Assert.assertEquals("search", user.getDefaultApp());
Assert.assertNotNull(user.getPassword());
user.getDefaultAppIsUserOverride();
Assert.assertNotNull(user.getDefaultAppSourceRole());
Assert.assertNotNull(user.getType());
// Probe
{
String tz = user.getTz();
user.setDefaultApp("search");
user.setEmail("none@noway.com");
user.setPassword("new-password");
user.setRealName("SDK-name");
if (service.versionCompare("4.3") >= 0) {
user.setRestartBackgroundJobs(false);
user.setTz("Pacific/Midway");
}
user.setRoles("power");
user.update();
user.refresh();
Assert.assertEquals("search", user.getDefaultApp());
Assert.assertEquals("none@noway.com", user.getEmail());
Assert.assertEquals("SDK-name", user.getRealName());
Assert.assertEquals(1, user.getRoles().length);
if (service.versionIsAtLeast("4.3")) {
Assert.assertEquals("Pacific/Midway", user.getTz());
}
Assert.assertTrue(contains(user.getRoles(), "power"));
if (service.versionIsAtLeast("4.3")) {
user.setTz(tz == null ? "" : tz);
}
user.setRoles(new String[] {"power"});
user.update();
user.refresh();
Assert.assertTrue(contains(user.getRoles(), "power"));
}
users.remove(username);
Assert.assertFalse(users.containsKey(username));
}
}
@SuppressWarnings("deprecation")
@Test
public void testClassicServiceArgs() {
ServiceArgs args = new ServiceArgs();
args.app = "myapp";
args.host = "myhost.splunk.com";
args.owner = "myuser";
args.port = 9999;
args.scheme = "https";
args.token = "Splunk MY_SESSION_KEY";
Service service = new Service(args);
Assert.assertEquals(args.app, service.getApp());
Assert.assertEquals(args.host, service.getHost());
Assert.assertEquals(args.owner, service.getOwner());
Assert.assertEquals((int) args.port, (int) service.getPort());
Assert.assertEquals(args.scheme, service.getScheme());
Assert.assertEquals(args.token, service.getToken());
}
@SuppressWarnings("deprecation")
@Test
public void testNewServiceArgs() {
ServiceArgs args = new ServiceArgs();
args.setApp("myapp");
args.setHost("myhost.splunk.com");
args.setOwner("myuser");
args.setPort(9999);
args.setScheme("https");
args.setToken("Splunk MY_SESSION_KEY");
Assert.assertEquals("Arg setters didn't replicate value to deprecated fields.",
args.app, "myapp");
Service service = new Service(args);
Assert.assertEquals(args.app, service.getApp());
Assert.assertEquals(args.host, service.getHost());
Assert.assertEquals(args.owner, service.getOwner());
Assert.assertEquals((int) args.port, (int) service.getPort());
Assert.assertEquals(args.scheme, service.getScheme());
Assert.assertEquals(args.token, service.getToken());
}
@Test
public void testNewServiceArgsAsMap() {
ServiceArgs args = new ServiceArgs();
args.put("app", "myapp");
args.put("host", "myhost.splunk.com");
args.put("owner", "myuser");
args.put("port", 9999);
args.put("scheme", "https");
args.put("token", "Splunk MY_SESSION_KEY");
Service service = new Service(args);
Assert.assertEquals("myapp", service.getApp());
Assert.assertEquals("myhost.splunk.com", service.getHost());
Assert.assertEquals("myuser", service.getOwner());
Assert.assertEquals(9999, (int) service.getPort());
Assert.assertEquals("https", service.getScheme());
Assert.assertEquals("Splunk MY_SESSION_KEY", service.getToken());
}
@Test
public void testNewServiceArgsWithDefaults() {
ServiceArgs args = new ServiceArgs();
Service service = new Service(args);
Assert.assertEquals(null, service.getApp());
Assert.assertEquals("localhost", service.getHost());
Assert.assertEquals(null, service.getOwner());
Assert.assertEquals(8089, (int) service.getPort());
Assert.assertEquals("https", service.getScheme());
Assert.assertEquals(null, service.getToken());
}
@Test
public void testConstructors() {
Service s;
s = new Service("localhost");
Assert.assertEquals("localhost", s.getHost());
Assert.assertEquals(8089, s.getPort());
Assert.assertEquals("https", s.getScheme());
s = new Service("localhost", 9999);
Assert.assertEquals("localhost", s.getHost());
Assert.assertEquals(9999, s.getPort());
Assert.assertEquals("https", s.getScheme());
s = new Service("localhost", 9999, "http");
Assert.assertEquals("localhost", s.getHost());
Assert.assertEquals(9999, s.getPort());
Assert.assertEquals("http", s.getScheme());
}
@Test
public void testSearch() throws IOException {
service.search(QUERY); // throws no exception
Job job = service.search(QUERY, new Args());
while (!job.isDone()) {
sleep(200);
}
InputStream jobOutput = job.getResults();
try {
ResultsReaderXml resultsReader = new ResultsReaderXml(jobOutput);
Map<String, String> event;
int nEvents = 0;
do {
event = resultsReader.getNextEvent();
if (event != null) {
nEvents += 1;
}
} while (event != null);
Assert.assertEquals(10, nEvents);
}
finally {
jobOutput.close();
}
}
@Test
public void testOneshot() throws IOException {
service.oneshotSearch(QUERY); // throws no exception
InputStream jobOutput = service.oneshotSearch(
QUERY,
new Args("output_mode", "json")
);
try {
ResultsReaderJson resultsReader = new ResultsReaderJson(jobOutput);
Map<String, String> event;
int nEvents = 0;
do {
event = resultsReader.getNextEvent();
if (event != null) {
nEvents += 1;
}
} while (event != null);
Assert.assertEquals(10, nEvents);
}
finally {
jobOutput.close();
}
}
// === Utility ===
private static void checkResponse(ResponseMessage response) {
Assert.assertEquals(200, response.getStatus());
// Make sure we can at least load the Atom response
AtomFeed.parseStream(response.getContent());
}
// Wait for the given job to be ready
private static Job ready(Job job) {
while (!job.isReady()) {
sleep(10);
}
return job;
}
@Test
public void testLoginWithNamespace() {
Args loginArgs = new Args();
loginArgs.add("username", command.opts.get("username"));
loginArgs.add("password", command.opts.get("password"));
loginArgs.add("sharing", "user");
loginArgs.add("owner", "admin");
loginArgs.add("app", "search");
loginArgs.add("host", command.opts.get("host"));
loginArgs.add("port", command.opts.get("port"));
Service.connect(loginArgs);
}
@Test
public void testHandleErrorsReturnedAsJson() {
JobExportArgs exportArgs = new JobExportArgs();
exportArgs.setOutputMode(JobExportArgs.OutputMode.JSON);
exportArgs.setSearchMode(JobExportArgs.SearchMode.REALTIME);
exportArgs.setEarliestTime("rt");
exportArgs.setLatestTime("rt");
try {
service.export("notasearchcommand", exportArgs);
} catch (Exception e) {
Assert.assertTrue(e.getMessage().contains("Unknown search command"));
return;
}
Assert.fail();
}
@Test
public void testDelete() {
Args deleteArgs = Args.create("output_mode", "json");
try {
service.delete("/services/search/jobs/foobar_doesntexist", deleteArgs);
} catch (HttpException e) {
Assert.assertEquals(404, e.getStatus());
Assert.assertNotNull(e.getDetail());
}
}
@Test
public void testPost() {
HashMap<String, Object> args = new HashMap<String, Object>();
args.put("foo", "bar");
ResponseMessage response;
response = service.post("/services/search/jobs", args);
Assert.assertEquals(200, response.getStatus());
Assert.assertTrue(firstLineIsXmlDtd(response.getContent()));
}
}