diff --git a/java/src/main/java/com/cloudera/api/ClouderaManagerClientBuilder.java b/java/src/main/java/com/cloudera/api/ClouderaManagerClientBuilder.java
index 52732514..1b6721d8 100644
--- a/java/src/main/java/com/cloudera/api/ClouderaManagerClientBuilder.java
+++ b/java/src/main/java/com/cloudera/api/ClouderaManagerClientBuilder.java
@@ -18,15 +18,9 @@
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.google.common.annotations.VisibleForTesting;
-
-import org.apache.cxf.configuration.jsse.TLSClientParameters;
-import org.apache.cxf.feature.AbstractFeature;
-import org.apache.cxf.feature.LoggingFeature;
-import org.apache.cxf.jaxrs.client.ClientConfiguration;
-import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
-import org.apache.cxf.jaxrs.client.WebClient;
-import org.apache.cxf.transport.http.HTTPConduit;
-import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
import java.net.URI;
import java.net.URISyntaxException;
@@ -34,9 +28,19 @@
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
+
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
+import org.apache.cxf.configuration.jsse.TLSClientParameters;
+import org.apache.cxf.feature.AbstractFeature;
+import org.apache.cxf.feature.LoggingFeature;
+import org.apache.cxf.jaxrs.client.ClientConfiguration;
+import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
+
public class ClouderaManagerClientBuilder {
public static final int DEFAULT_TCP_PORT = 7180;
public static final long DEFAULT_CONNECTION_TIMEOUT = 0;
@@ -61,6 +65,38 @@ public class ClouderaManagerClientBuilder {
private boolean validateCn = true;
private TrustManager[] trustManagers = null;
+ /**
+ * Cache JAXRSClientFactoryBean per proxyType.
+ *
+ * We need a cache because CXF stores stubs
+ * ({@link org.apache.cxf.jaxrs.model.ClassResourceInfo} objects) as a reference
+ * inside JAXRSServiceFactoryBean, which is composed within instances of
+ * {@link JAXRSClientFactoryBean}.
+ *
+ * This avoids:
+ * - creating a lot of temporaries generated during the proxy creation for
+ * each client
+ *
+ * - ensures that different proxies of the same type actually share the same
+ * ClassResourceInfo, thus reducing aggregate usage
+ *
+ * Also, as a useful side effect, generates proxies with cached proxy types faster.
+ */
+ private static final LoadingCache
+ * This argument is for ADVANCED users only.
+ *
+ * By default, this call will fetch the first 100 audit events (sorted from most
+ * recent to oldest) corresponding to a 1 day window based on provided end time
+ * (which defaults to the current CM server time). The startTime and
+ * endTime parameters can be used to control the window being queried.
+ *
+ * Audit events for CM managed services are only retrieved if Cloudera
+ * Navigator server is running.
+ *
+ * @param maxResults Maximum number of audits to return
+ * @param resultOffset Offset of audits to return
+ * @param startTime Start of the period to query (defaults to 1 day ago
+ * relative to endTime)
+ * @param endTime End of the period to query (defaults to current time)
+ * @param query
+ * The query to filter out audits in the system. It accepts
+ * querying the intersection of a list of constraints,
+ * joined together with semicolons (without spaces). For example:
+ *
+ * The only supported operator is ";" (Boolean AND). Boolean OR is
+ * not supported.
+ *
+ * The supported comparators are == and !=
+ * Note that "LIKE" comparison is supported using the wild card syntax,
+ * for example foo==*value*. Asterisk is interpreted as a wild
+ * card character and must not be part of the value. (LIKE comparison
+ * queries are converted to standard SQL LIKE syntax, so any % (%25)
+ * character in a value that also contains a wild card will be
+ * interpreted as a wild card.)
+ *
+ * Values for time related query parameters (startTime and
+ * endTime) should be ISO8601 timestamps.
+ *
+ * This command applies only to HDFS NameNode, JournalNode, and Failover
+ * Controller roles. In order to migrate these roles:
+ * If the active NameNode is selected for migration, a manual failover
+ * will be performed before the role is migrated. The role will remain in
+ * standby mode after the migration is complete.
+ * When migrating a NameNode role, the co-located Failover Controller
+ * role must be migrated as well if automatic failover is enabled. The
+ * Failover Controller role name must be included in the list of role
+ * names to migrate specified in the arguments to this command (it will
+ * not be included implicitly). This command does not allow a Failover
+ * Controller role to be moved by itself, although it is possible to move
+ * a JournalNode independently.
+ *
+ * Available since API v10.
+ *
+ * @param hostId The ID of the host on which the roles to migrate currently
+ * reside
+ * @param args Arguments for the command.
+ * @return Information about the submitted command.
+ */
+ @POST
+ @Path("/{hostId}/commands/migrateRoles")
+ public ApiCommand migrateRoles(@PathParam(HOST_ID) String hostId,
+ ApiMigrateRolesArguments args);
+}
diff --git a/java/src/main/java/com/cloudera/api/v10/RoleCommandsResourceV10.java b/java/src/main/java/com/cloudera/api/v10/RoleCommandsResourceV10.java
new file mode 100644
index 00000000..6bdd83a4
--- /dev/null
+++ b/java/src/main/java/com/cloudera/api/v10/RoleCommandsResourceV10.java
@@ -0,0 +1,55 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. Cloudera, Inc. 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 com.cloudera.api.v10;
+
+import com.cloudera.api.model.ApiBulkCommandList;
+import com.cloudera.api.model.ApiRoleNameList;
+import com.cloudera.api.v8.RoleCommandsResourceV8;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+@Consumes({ MediaType.APPLICATION_JSON })
+@Produces({ MediaType.APPLICATION_JSON })
+public interface RoleCommandsResourceV10 extends RoleCommandsResourceV8 {
+ /**
+ * Refresh a role's data.
+ *
+ * For MapReduce services, this command should be executed on JobTracker
+ * roles. It refreshes the role's queue and node information.
+ *
+ * For HDFS services, this command should be executed on NameNode or
+ * DataNode roles. For NameNodes, it refreshes the role's node list.
+ * For DataNodes, it refreshes the role's data directory list.
+ *
+ * For YARN services, this command should be executed on ResourceManager
+ * roles. It refreshes the role's queue and node information.
+ *
+ * Available since API v1. DataNode data directories refresh available
+ * since API v10.
+ *
+ * @param roleNames The names of the roles.
+ * @return A list of submitted commands.
+ */
+ @POST
+ @Path("/refresh")
+ public ApiBulkCommandList refreshCommand(
+ ApiRoleNameList roleNames);
+}
diff --git a/java/src/main/java/com/cloudera/api/v10/RootResourceV10.java b/java/src/main/java/com/cloudera/api/v10/RootResourceV10.java
new file mode 100644
index 00000000..f8832b82
--- /dev/null
+++ b/java/src/main/java/com/cloudera/api/v10/RootResourceV10.java
@@ -0,0 +1,46 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. Cloudera, Inc. 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 com.cloudera.api.v10;
+
+import com.cloudera.api.v9.RootResourceV9;
+
+import javax.ws.rs.Path;
+
+@Path("")
+public interface RootResourceV10 extends RootResourceV9 {
+
+ /**
+ * @return The clusters resource handler.
+ */
+ @Override
+ @Path("/clusters")
+ public ClustersResourceV10 getClustersResource();
+
+ /**
+ * @return The hosts resource handler.
+ */
+ @Override
+ @Path("/hosts")
+ public HostsResourceV10 getHostsResource();
+
+ /**
+ * @return Audits resource handler.
+ */
+ @Override
+ @Path("/audits")
+ public AuditsResourceV10 getAuditsResource();
+
+}
diff --git a/java/src/main/java/com/cloudera/api/v10/ServicesResourceV10.java b/java/src/main/java/com/cloudera/api/v10/ServicesResourceV10.java
new file mode 100644
index 00000000..db095beb
--- /dev/null
+++ b/java/src/main/java/com/cloudera/api/v10/ServicesResourceV10.java
@@ -0,0 +1,118 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. Cloudera, Inc. 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 com.cloudera.api.v10;
+
+import static com.cloudera.api.Parameters.SERVICE_NAME;
+
+import com.cloudera.api.model.ApiCommand;
+import com.cloudera.api.v8.ServicesResourceV8;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+@Consumes({ MediaType.APPLICATION_JSON })
+@Produces({ MediaType.APPLICATION_JSON })
+public interface ServicesResourceV10 extends ServicesResourceV8 {
+
+ /**
+ * @return The role command resource handler.
+ */
+ @Override
+ @Path("/{serviceName}/roleCommands")
+ public RoleCommandsResourceV10 getRoleCommandsResource(
+ @PathParam(SERVICE_NAME) String serviceName);
+
+ /**
+ * Runs Hue's dumpdata command.
+ *
+ * Available since API v10.
+ *
+ * @param serviceName The name of the service
+ * @return Information about the submitted command.
+ */
+ @POST
+ @Path("/{serviceName}/commands/hueDumpDb")
+ public ApiCommand hueDumpDbCommand(
+ @PathParam(SERVICE_NAME) String serviceName);
+
+ /**
+ * Runs Hue's loaddata command.
+ *
+ * Available since API v10.
+ *
+ * @param serviceName The name of the service
+ * @return Information about the submitted command.
+ */
+ @POST
+ @Path("/{serviceName}/commands/hueLoadDb")
+ public ApiCommand hueLoadDbCommand(
+ @PathParam(SERVICE_NAME) String serviceName);
+
+ /**
+ * Runs Hue's syncdb command.
+ *
+ * Available since API v10.
+ *
+ * @param serviceName The name of the service
+ * @return Information about the submitted command.
+ */
+ @POST
+ @Path("/{serviceName}/commands/hueSyncDb")
+ public ApiCommand hueSyncDbCommand(
+ @PathParam(SERVICE_NAME) String serviceName);
+
+ /**
+ * Create the Oozie Server Database. Only works with embedded postgresql
+ * database.
+ *
+ * This command is to be run whenever a new user and database need to be
+ * created in the embedded postgresql database for an Oozie service. This
+ * command should usually be followed by a call to createOozieDb.
+ *
+ * Available since API v10.
+ *
+ * @param serviceName
+ * Name of the Oozie service on which to run the command.
+ * @return Information about the submitted command
+ */
+ @POST
+ @Consumes()
+ @Path("/{serviceName}/commands/oozieCreateEmbeddedDatabase")
+ public ApiCommand oozieCreateEmbeddedDatabaseCommand(
+ @PathParam(SERVICE_NAME) String serviceName);
+
+ /**
+ * Create the Sqoop2 Server Database tables.
+ *
+ * This command is to be run whenever a new database has been specified. Will
+ * do nothing if tables already exist. Will not perform an upgrade. Only
+ * available when Sqoop2 Server is stopped.
+ *
+ * Available since API v10.
+ *
+ * @param serviceName Name of the Sentry service on which to run the command.
+ * @return Information about the submitted command
+ */
+ @POST
+ @Consumes()
+ @Path("/{serviceName}/commands/sqoopCreateDatabaseTables")
+ public ApiCommand sqoopCreateDatabaseTablesCommand(
+ @PathParam(SERVICE_NAME) String serviceName);
+}
diff --git a/java/src/main/java/com/cloudera/api/v10/package-info.java b/java/src/main/java/com/cloudera/api/v10/package-info.java
new file mode 100644
index 00000000..4e5f703e
--- /dev/null
+++ b/java/src/main/java/com/cloudera/api/v10/package-info.java
@@ -0,0 +1,21 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. Cloudera, Inc. 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.
+
+/**
+ * API version 10, introduced in Cloudera Manager 5.4.0.
+ */
+
+package com.cloudera.api.v10;
\ No newline at end of file
diff --git a/java/src/main/java/com/cloudera/api/v2/ClouderaManagerResourceV2.java b/java/src/main/java/com/cloudera/api/v2/ClouderaManagerResourceV2.java
index 386092d5..e95bfce9 100644
--- a/java/src/main/java/com/cloudera/api/v2/ClouderaManagerResourceV2.java
+++ b/java/src/main/java/com/cloudera/api/v2/ClouderaManagerResourceV2.java
@@ -80,6 +80,10 @@ public ApiDeployment getDeployment(
* all changes will be rolled back leaving the system exactly as it was
* before calling this method. The system will never be left in a state
* where part of the deployment is created and other parts are not.
+ *
* Available since API v2.
diff --git a/java/src/main/java/com/cloudera/api/v8/AuditsResourceV8.java b/java/src/main/java/com/cloudera/api/v8/AuditsResourceV8.java
index 7853b7c4..05c201cb 100644
--- a/java/src/main/java/com/cloudera/api/v8/AuditsResourceV8.java
+++ b/java/src/main/java/com/cloudera/api/v8/AuditsResourceV8.java
@@ -38,10 +38,10 @@ public interface AuditsResourceV8 extends AuditsResource {
* Fetch audit events from Cloudera Manager (CM) and CM managed services
* like HDFS, HBase, Impala, Hive, and Sentry.
*
- * By default, this call will fetch all audit events corresponding to a
- * 1 day window based on provided end time (which defaults to the current
- * CM server time). The startTime and endTime parameters
- * can be used to control the window being queried.
+ * By default, this call will fetch the first 100 audit events (sorted from most
+ * recent to oldest) corresponding to a 1 day window based on provided end time
+ * (which defaults to the current CM server time). The startTime and
+ * endTime parameters can be used to control the window being queried.
*
* Audit events for CM managed services are only retrieved if Cloudera
* Navigator server is running.
diff --git a/java/src/test/java/com/cloudera/api/ClouderaManagerClientBuilderTest.java b/java/src/test/java/com/cloudera/api/ClouderaManagerClientBuilderTest.java
index fefb54bb..bbf020d7 100644
--- a/java/src/test/java/com/cloudera/api/ClouderaManagerClientBuilderTest.java
+++ b/java/src/test/java/com/cloudera/api/ClouderaManagerClientBuilderTest.java
@@ -22,6 +22,7 @@
import java.net.URL;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
public class ClouderaManagerClientBuilderTest {
@@ -75,4 +76,24 @@ public void testURLGeneration() throws MalformedURLException {
// expected
}
}
+
+ @Test
+ public void testResourceConfig() {
+ ClouderaManagerClientBuilder builder = new ClouderaManagerClientBuilder();
+ ApiRootResource a = newProxy(builder);
+ assertNotNull(a);
+ ApiRootResource b = newProxy(builder);
+ assertNotNull(b);
+
+ ClouderaManagerClientBuilder.clearCachedResources();
+ // test after clear
+ assertNotNull(newProxy(builder));
+ }
+
+ public ApiRootResource newProxy(ClouderaManagerClientBuilder builder) {
+ return builder.withHost("localhost")
+ .withPort(1)
+ .enableLogging()
+ .build();
+ }
}
diff --git a/java/src/test/java/com/cloudera/api/model/ApiModelTest.java b/java/src/test/java/com/cloudera/api/model/ApiModelTest.java
index 8f50ce06..1457c98c 100644
--- a/java/src/test/java/com/cloudera/api/model/ApiModelTest.java
+++ b/java/src/test/java/com/cloudera/api/model/ApiModelTest.java
@@ -926,6 +926,7 @@ private ApiHdfsReplicationArguments newHdfsReplicationArguments() {
hdfsArgs.setLogPath("log1");
hdfsArgs.setSkipChecksumChecks(true);
hdfsArgs.setSkipTrash(true);
+ hdfsArgs.setPreserveXAttrs(true);
hdfsArgs.setReplicationStrategy(ReplicationStrategy.DYNAMIC);
return hdfsArgs;
}
@@ -965,6 +966,7 @@ private ApiCluster newCluster() {
cluster.setMaintenanceMode(true);
cluster.setName("mycluster");
cluster.setDisplayName("mycluster-displayName");
+ cluster.setClusterUrl("http://some-url:7180/cmf/clusterRedirect/mycluster");
cluster.setVersion(ApiClusterVersion.CDH4);
cluster.setFullVersion("4.1.2");
return cluster;
diff --git a/python/.gitignore b/python/.gitignore
index 3cfea3fd..5489775f 100644
--- a/python/.gitignore
+++ b/python/.gitignore
@@ -1,5 +1,6 @@
build/
dist/
+doc/
*.egg-info/
.git-hash
diff --git a/python/Makefile b/python/Makefile
index dfe2a557..e556e230 100644
--- a/python/Makefile
+++ b/python/Makefile
@@ -14,10 +14,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+DOCDIR ?= doc
+
.PHONY: help
help:
@echo 'The build targets are:'
@echo ' dist : Create a source distribution tarball'
+ @echo ' test : Run unit tests'
+ @echo ' doc : Generate epydoc format documentation'
+ @echo ' clean : Clean up all generated files'
.PHONY: test
test:
@@ -33,5 +38,10 @@ dist: test
clean:
rm -rf *.egg-info
rm -rf dist
+ rm -rf doc
rm -rf build
find . -name *.py[co] -exec rm -f {} \;
+
+.PHONY: doc
+doc:
+ epydoc -v --html -o $(DOCDIR) -n python-cm_api `find src -name "*.py"`
diff --git a/python/examples/timeseries.py b/python/examples/timeseries.py
index 44823293..3fa9056d 100644
--- a/python/examples/timeseries.py
+++ b/python/examples/timeseries.py
@@ -17,7 +17,7 @@
"""
-Given a query amd an optional time range, show all timeseries
+Given a query and an optional time range, show all timeseries
data that matches the given query in the given time range.
Usage: %s [options] query
@@ -69,6 +69,7 @@
CM_HOST = 'localhost'
CM_USER = 'admin'
CM_PASSWD = 'admin'
+CM_USE_TLS = False
LOG = logging.getLogger(__name__)
@@ -76,7 +77,7 @@ class TimeSeriesQuery(object):
"""
"""
def __init__(self):
- self._api = ApiResource(CM_HOST, username=CM_USER, password=CM_PASSWD)
+ self._api = ApiResource(CM_HOST, username=CM_USER, password=CM_PASSWD, use_tls=CM_USE_TLS)
def query(self, query, from_time, to_time):
return self._api.query_timeseries(query, from_time, to_time)
diff --git a/python/setup.py b/python/setup.py
index e8845c4d..f5a22d15 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -33,6 +33,9 @@
if platform == 'darwin':
install_requires += ['readline']
+# Optional PySocks support
+extras_require = dict(Socks=['PySocks >= 1.5.0'])
+
setup(
name = 'cm_api',
version = '10.0.0', # Compatible with API v10 (CM 5.4)
@@ -43,6 +46,7 @@
# Project uses simplejson, so ensure that it gets installed or upgraded
# on the target machine
install_requires = install_requires,
+ extras_require = extras_require,
author = 'Cloudera, Inc.',
author_email = 'scm-users@cloudera.org',
diff --git a/python/src/cm_api/api_client.py b/python/src/cm_api/api_client.py
index 47144eaf..a33dc532 100644
--- a/python/src/cm_api/api_client.py
+++ b/python/src/cm_api/api_client.py
@@ -209,6 +209,20 @@ def create_user(self, username, password, roles):
"""
return users.create_user(self, username, password, roles)
+ def update_user(self, username, password, roles):
+ """
+ Update a user.
+
+ Replaces the user's details with those provided.
+
+ @param username: Username
+ @param password: Password
+ @param roles: List of roles for the user. This should be [] for a
+ regular user, or ['ROLE_ADMIN'] for an admin.
+ @return: An ApiUser object
+ """
+ return users.update_user(self, users.ApiUser(self, username, password, roles))
+
def delete_user(self, username):
"""
Delete user by username.
diff --git a/python/src/cm_api/endpoints/cms.py b/python/src/cm_api/endpoints/cms.py
index 6c14e742..55f0196c 100644
--- a/python/src/cm_api/endpoints/cms.py
+++ b/python/src/cm_api/endpoints/cms.py
@@ -201,9 +201,10 @@ def collect_diagnostic_data_45(self, end_datetime, bundle_size_bytes, cluster_na
args = {
'endTime': end_datetime.isoformat(),
'bundleSizeBytes': bundle_size_bytes,
- 'clusterName': cluster_name,
- 'roles': roles
+ 'clusterName': cluster_name
}
+ if self._get_resource_root().version >= 10:
+ args['roles'] = roles
return self._cmd('collectDiagnosticData', data=args)
def hosts_decommission(self, host_names):
diff --git a/python/src/cm_api/http_client.py b/python/src/cm_api/http_client.py
index 81722403..08b65c3a 100644
--- a/python/src/cm_api/http_client.py
+++ b/python/src/cm_api/http_client.py
@@ -14,11 +14,24 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import os
import cookielib
import logging
import posixpath
import types
import urllib
+
+try:
+ import socks
+ import socket
+ socks_server = os.environ.get("SOCKS_SERVER", None)
+ if socks_server:
+ host, port = socks_server.split(":")
+ socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, host, int(port))
+ socket.socket = socks.socksocket
+except ImportError:
+ pass
+
import urllib2
__docformat__ = "epytext"
diff --git a/python/src/cm_api/resource.py b/python/src/cm_api/resource.py
index fda0e53f..f96b9c6a 100644
--- a/python/src/cm_api/resource.py
+++ b/python/src/cm_api/resource.py
@@ -14,6 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import os
try:
import json
except ImportError:
@@ -22,6 +23,15 @@
import posixpath
import time
import socket
+try:
+ import socks
+ socks_server = os.environ.get("SOCKS_SERVER", None)
+ if socks_server:
+ host, port = socks_server.split(":")
+ socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, host, int(port))
+ socket.socket = socks.socksocket
+except ImportError:
+ pass
import urllib2
LOG = logging.getLogger(__name__)
diff --git a/python/src/cm_api_tests/test_apiclient.py b/python/src/cm_api_tests/test_apiclient.py
new file mode 100644
index 00000000..f46fd1af
--- /dev/null
+++ b/python/src/cm_api_tests/test_apiclient.py
@@ -0,0 +1,29 @@
+# Licensed to Cloudera, Inc. under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. Cloudera, Inc. 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.
+
+import unittest
+
+from cm_api.endpoints import users
+from cm_api_tests import utils
+
+
+class ApiResourceTest(unittest.TestCase):
+ def test_update_user(self):
+ resource = utils.MockApiResource(self)
+
+ expected = { 'name' : 'test_user', 'password': 'test_password','roles' : ['ROLE_LIMITED'] }
+ resource.expect("PUT", "/users/test_user", data=expected, retdata=expected)
+ resource.update_user(expected['name'], expected['password'], expected['roles'])
\ No newline at end of file
diff --git a/python/src/cm_api_tests/test_yarn.py b/python/src/cm_api_tests/test_yarn.py
index f6e22a53..ae104b58 100644
--- a/python/src/cm_api_tests/test_yarn.py
+++ b/python/src/cm_api_tests/test_yarn.py
@@ -15,13 +15,17 @@
# limitations under the License.
import datetime
-import json
import unittest
from cm_api.endpoints.clusters import *
from cm_api.endpoints.services import *
from cm_api.endpoints.types import *
from cm_api_tests import utils
+try:
+ import json
+except ImportError:
+ import simplejson as json
+
class TestYarn(unittest.TestCase):
def test_get_yarn_applications(self):
diff --git a/python/src/cm_api_tests/utils.py b/python/src/cm_api_tests/utils.py
index ac43419f..9b5bdf77 100644
--- a/python/src/cm_api_tests/utils.py
+++ b/python/src/cm_api_tests/utils.py
@@ -14,9 +14,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import types
+
from cm_api import api_client
from cm_api.endpoints.types import Attr
from cm_api.resource import Resource
+from cm_api.api_client import ApiResource
try:
import json
@@ -74,6 +77,15 @@ def expect(self, method, reqpath, params=None, data=None, headers=None,
"""
self._next_expect = (method, reqpath, params, data, headers, retdata)
+
+class MockApiResource(MockResource):
+ """Mock class for ApiResource"""
+
+ # workaround to make this method available for testing
+ def update_user(self, *args, **kwargs):
+ return ApiResource.update_user.__get__(self, ApiResource)(*args, **kwargs)
+
+
def deserialize(raw_data, cls):
"""
Deserializes raw JSON data into an instance of cls.
diff --git a/python/src/cm_shell/cmps.py b/python/src/cm_shell/cmps.py
index f728c129..8b90ada8 100755
--- a/python/src/cm_shell/cmps.py
+++ b/python/src/cm_shell/cmps.py
@@ -593,6 +593,7 @@ def main():
parser.add_argument('--password', action='store', dest='password')
parser.add_argument('-e', '--execute', action='store', dest='execute')
parser.add_argument('-s', '--seperator', action='store', dest='seperator')
+ parser.add_argument('-t', '--tls', action='store_const', dest='use_tls', const=True, default=False)
args = parser.parse_args()
# Check if a username was suplied, if not, prompt the user
@@ -605,12 +606,12 @@ def main():
# Attempt to authenticate using the API
global api
- api = ApiResource(args.hostname, args.port, args.username, args.password)
+ api = ApiResource(args.hostname, args.port, args.username, args.password, args.use_tls)
try:
api.echo("ping")
except ApiException:
try:
- api = ApiResource(args.hostname, args.port, args.username, args.password, version=1)
+ api = ApiResource(args.hostname, args.port, args.username, args.password, args.use_tls, version=1)
api.echo("ping")
except ApiException:
print("Unable to Authenticate")
+ * The private key, if specified, needs to be a
+ * standard PEM-encoded key as a single string, with all line breaks
+ * replaced with the line-feed control character '\n'.
+ *
+ * A value will typically look like the following string:
+ *
+ * -----BEGIN RSA PRIVATE KEY-----\n[base-64 encoded key]\n-----END RSA PRIVATE KEY-----
+ *
*/
@XmlElement
public String getPrivateKey() {
diff --git a/java/src/main/java/com/cloudera/api/model/ApiMigrateRolesArguments.java b/java/src/main/java/com/cloudera/api/model/ApiMigrateRolesArguments.java
new file mode 100644
index 00000000..4182de42
--- /dev/null
+++ b/java/src/main/java/com/cloudera/api/model/ApiMigrateRolesArguments.java
@@ -0,0 +1,98 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. Cloudera, Inc. 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 com.cloudera.api.model;
+
+import com.cloudera.api.ApiUtils;
+
+import com.google.common.base.Objects;
+
+import java.util.List;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name="migrateRolesArgs")
+public class ApiMigrateRolesArguments {
+
+ private List
+ *
+ *
+ * Following are valid selectors for the query (if applicable to the
+ * audit):
+ *
+ *
+ *
+ *
+ * Selector
+ * Description
+ * SCM
+ * HDFS
+ * HBase
+ * Hive
+ * Impala
+ * Sentry
+ *
+ *
+ * service
+ * Cloudera Manager Service
+ * x
+ * x
+ * x
+ * x
+ * x
+ * x
+ *
+ *
+ * operation
+ * Operation name
+ * x
+ * x
+ * x
+ * x
+ * x
+ * x
+ *
+ *
+ * username
+ * User name
+ * x
+ * x
+ * x
+ * x
+ * x
+ * x
+ *
+ *
+ * impersonator
+ * Impersonator
+ *
+ * x
+ * x
+ * x
+ * x
+ * x
+ *
+ *
+ * ip_address
+ * IP Address
+ * x
+ * x
+ * x
+ * x
+ * x
+ * x
+ *
+ *
+ * allowed
+ * Whether the request was allowed or denied
+ * x
+ * x
+ * x
+ * x
+ * x
+ * x
+ *
+ *
+ * qualifier
+ * Column qualifier
+ *
+ *
+ * x
+ *
+ *
+ *
+ *
+ *
+ * source
+ * Source resource of the operation
+ * x
+ * x
+ * x
+ * x
+ * x
+ *
+ *
+ *
+ * destination
+ * Destination resource of the operation
+ *
+ * x
+ * x
+ * x
+ * x
+ *
+ *
+ *
+ * hostIpAddress
+ * Host IP Address
+ * x
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * role
+ * Cloudera Manager Role
+ * x
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * family
+ * Column family
+ *
+ *
+ * x
+ *
+ *
+ *
+ *
+ *
+ * database_name
+ * Database name
+ *
+ *
+ *
+ * x
+ * x
+ * x
+ *
+ *
+ * table_name
+ * Table name
+ *
+ *
+ * x
+ * x
+ * x
+ * x
+ *
+ *
+ * object_type
+ * Type of object being handled
+ *
+ *
+ *
+ * x
+ * x
+ * x
+ *
+ *
+ * operation_text
+ * Command/query text
+ *
+ *
+ *
+ * x
+ * x
+ * x
+ *
+ *
+ * Migrating a NameNode or JournalNode role requires cluster downtime.
+ * HDFS, along with all of its dependent services, will be stopped at the
+ * beginning of the migration process, and restarted at its conclusion.
+ *