Skip to content

Cm5 5.10.0 #59

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 160 additions & 47 deletions java/api-docs.fmt
Original file line number Diff line number Diff line change
@@ -1064,10 +1064,10 @@
A service is an abstract entity providing a capability in a cluster.
Examples of services are HDFS, MapReduce, YARN, and HBase. A service
is usually distributed, and contains a set of roles that physically
run on the cluster. A service has its own configuration, status,
metrics, and roles. You may issue commands against a service, or
against a set of roles in bulk. Additionally, an HDFS service has
nameservices, and a MapReduce service has activities.
run on the cluster. A service has its own configuration, status and
roles. You may issue commands against a service, or against a set
of roles in bulk. Additionally, an HDFS service has nameservices,
and a MapReduce service has activities.
<p>
All services belong to a cluster (except for the Cloudera Management
Service), and is uniquely identified by its name within a Cloudera
@@ -1083,8 +1083,8 @@
processes.) Once created, a role cannot be reassigned to a different
host. You need to delete and re-create it.
<p>
A role has its own configuration, status and metrics. API commands on
roles are always issued in bulk at the service level.
A role has its own configuration and status. API commands on roles
are always issued in bulk at the service level.
</dd>
<dt>Role Type</dt>
<dd>
@@ -1119,6 +1119,18 @@
The operation of this service is similar to other Hadoop services, except
that the Management Service does not belong to a cluster.
</dd>
<dt>Metrics</dt>
<dd>
<p>
A metric is a property that can be measured to quantify the state of an
entity or activity, such as the number of open file descriptors or CPU
utilization percentage. Full list of metric schema is available through
Cloudera Manager API /timeseries/schema endpoint.
<p>
Cloudera Manager enables retrieving of metric data using a launguage
called tsquery. Please see tsquery documentation for more details on
how to write a tsquery.
</dd>
</dl>

<h2>Debugging the API</h2>
@@ -1504,56 +1516,157 @@
}
}</code>

<h3>Metrics</h3>
<h3>Querying metric data</h3>

<p>In the Enterprise Edition, you can get metrics related to hosts,
services, roles and activities. The call by default fetches data points from
the last 5 minutes.
<p>
Getting dfs capacity metric data for service HDFS-1.
<code>
$ curl -u admin:admin \
'http://localhost:7180/api/v1/clusters/Cluster%201%20-%20CDH4/services/hdfs1/metrics?metrics=dfs_capacity_used_non_hdfs&amp;metrics=dfs_capacity'
'http://localhost:7180/api/v11/timeseries?query=select%20dfs_capacity,%20dfs_capacity_used,%20dfs_capacity_used_non_hdfs%20where%20entityName=HDFS-1'

{
"items" : [ {
"name" : "dfs_capacity_used_non_hdfs",
"context" : "hdfs1:nameservice1",
"data" : [ {
"value" : 0.0,
"timestamp" : "2012-05-06T10:25:46.000Z"
}, {
"value" : 0.0,
"timestamp" : "2012-05-06T10:26:46.000Z"
}, {
"value" : 0.0,
"timestamp" : "2012-05-06T10:27:46.000Z"
}, {
"value" : 0.0,
"timestamp" : "2012-05-06T10:28:46.000Z"
}, {
"value" : 0.0,
"timestamp" : "2012-05-06T10:29:46.000Z"
} ],
"unit" : "bytes"
}, {
"name" : "dfs_capacity",
"context" : "hdfs1:nameservice1",
"data" : [ {
"value" : 3.2103841792E10,
"timestamp" : "2012-05-06T10:25:46.000Z"
}, {
"value" : 3.2103841792E10,
"timestamp" : "2012-05-06T10:26:46.000Z"
}, {
"value" : 3.2103841792E10,
"timestamp" : "2012-05-06T10:27:46.000Z"
"timeSeries": [ {
"metadata": {
"metricName": "dfs_capacity",
"entityName": "HDFS-1",
"startTime": "2015-09-17T23:42:22.533Z",
"endTime": "2015-09-17T23:47:22.533Z",
"attributes": {
"clusterName": "Cluster 1",
"category": "SERVICE",
"clusterDisplayName": "Cluster 1",
"active": "true",
"serviceType": "HDFS",
"serviceDisplayName": "HDFS-1",
"version": "CDH 5.7.0",
"serviceName": "HDFS-1",
"entityName": "HDFS-1"
},
"unitNumerators": [
"bytes"
],
"unitDenominators": [],
"expression": "SELECT dfs_capacity WHERE entityName = \"HDFS-1\" AND category = SERVICE",
"metricCollectionFrequencyMs": 60000,
"rollupUsed": "RAW"
},
"data": [ {
"timestamp": "2015-09-17T23:43:10.599Z",
"value": 86909397813,
"type": "SAMPLE"
}, {
"timestamp": "2015-09-17T23:44:10.605Z",
"value": 86909397813,
"type": "SAMPLE"
}, {
"timestamp": "2015-09-17T23:45:10.608Z",
"value": 86909397813,
"type": "SAMPLE"
}, {
"timestamp": "2015-09-17T23:46:10.615Z",
"value": 86909397813,
"type": "SAMPLE"
}, {
"timestamp": "2015-09-17T23:47:15.613Z",
"value": 86909397813,
"type": "SAMPLE"
} ]
}, {
"value" : 3.2103841792E10,
"timestamp" : "2012-05-06T10:28:46.000Z"
"metadata": {
"metricName": "dfs_capacity_used",
"entityName": "HDFS-1",
"startTime": "2015-09-17T23:42:22.533Z",
"endTime": "2015-09-17T23:47:22.533Z",
"attributes": {
"clusterName": "Cluster 1",
"category": "SERVICE",
"clusterDisplayName": "Cluster 1",
"active": "true",
"serviceType": "HDFS",
"serviceDisplayName": "HDFS-1",
"version": "CDH 5.7.0",
"serviceName": "HDFS-1",
"entityName": "HDFS-1"
},
"unitNumerators": [
"bytes"
],
"unitDenominators": [],
"expression": "SELECT dfs_capacity_used WHERE entityName = \"HDFS-1\" AND category = SERVICE",
"metricCollectionFrequencyMs": 60000,
"rollupUsed": "RAW"
},
"data": [ {
"timestamp": "2015-09-17T23:43:10.599Z",
"value": 1728884736,
"type": "SAMPLE"
}, {
"timestamp": "2015-09-17T23:44:10.605Z",
"value": 1728884736,
"type": "SAMPLE"
}, {
"timestamp": "2015-09-17T23:45:10.608Z",
"value": 1728884736,
"type": "SAMPLE"
}, {
"timestamp": "2015-09-17T23:46:10.615Z",
"value": 1728884736,
"type": "SAMPLE"
}, {
"timestamp": "2015-09-17T23:47:15.613Z",
"value": 1728884736,
"type": "SAMPLE"
} ]
}, {
"value" : 3.2103841792E10,
"timestamp" : "2012-05-06T10:29:46.000Z"
"metadata": {
"metricName": "dfs_capacity_used_non_hdfs",
"entityName": "HDFS-1",
"startTime": "2015-09-17T23:42:22.533Z",
"endTime": "2015-09-17T23:47:22.533Z",
"attributes": {
"clusterName": "Cluster 1",
"category": "SERVICE",
"clusterDisplayName": "Cluster 1",
"active": "true",
"serviceType": "HDFS",
"serviceDisplayName": "HDFS-1",
"version": "CDH 5.7.0",
"serviceName": "HDFS-1",
"entityName": "HDFS-1"
},
"unitNumerators": [
"bytes"
],
"unitDenominators": [],
"expression": "SELECT dfs_capacity_used_non_hdfs WHERE entityName = \"HDFS-1\" AND category = SERVICE",
"metricCollectionFrequencyMs": 60000,
"rollupUsed": "RAW"
},
"data": [ {
"timestamp": "2015-09-17T23:43:10.599Z",
"value": 1610609973,
"type": "SAMPLE"
}, {
"timestamp": "2015-09-17T23:44:10.605Z",
"value": 1610609973,
"type": "SAMPLE"
}, {
"timestamp": "2015-09-17T23:45:10.608Z",
"value": 1610609973,
"type": "SAMPLE"
}, {
"timestamp": "2015-09-17T23:46:10.615Z",
"value": 1610609973,
"type": "SAMPLE"
}, {
"timestamp": "2015-09-17T23:47:15.613Z",
"value": 1610609973,
"type": "SAMPLE"
} ]
} ],
"unit" : "bytes"
"warnings": [],
"timeSeriesQuery": "select dfs_capacity, dfs_capacity_used, dfs_capacity_used_non_hdfs where entityName=HDFS-1"
} ]</code>

[/@boilerplate]
6 changes: 3 additions & 3 deletions java/enunciate.xml
Original file line number Diff line number Diff line change
@@ -2,18 +2,18 @@
xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.27.xsd">

<api-classes>
<include pattern="com.cloudera.api.v10.*"/>
<include pattern="com.cloudera.api.v15.*"/>
</api-classes>

<services>
<rest defaultRestSubcontext="/api/v10"/>
<rest defaultRestSubcontext="/api/v15"/>
</services>

<modules>
<docs splashPackage="com.cloudera.api"
copyright="Cloudera, Inc. All rights reserved."
docsDir="apidocs"
title="Cloudera Manager API v10"
title="Cloudera Manager API v15"
groupRestResources="byPath"
freemarkerXMLProcessingTemplate="api-docs.fmt"
css="static/cms/css/api-docs.css"
44 changes: 39 additions & 5 deletions java/pom.xml
Original file line number Diff line number Diff line change
@@ -5,10 +5,10 @@
<groupId>com.cloudera.api</groupId>
<artifactId>cloudera-manager-api</artifactId>
<name>Cloudera Manager API</name>
<version>5.10.0-SNAPSHOT</version>
<version>5.10.0</version>

<properties>
<cxf.version>2.7.5</cxf.version>
<cxf.version>2.7.7</cxf.version>
<guava.version>14.0</guava.version>
<jackson2.version>2.1.0</jackson2.version>
<joda.version>2.1</joda.version>
@@ -21,7 +21,7 @@
<distributionManagement>
<repository>
<id>cdh.releases.repo</id>
<url>http://maven.jenkins.cloudera.com:8081/artifactory/libs-release-local</url>
<url>http://maven.jenkins.cloudera.com:8081/artifactory/cdh-staging-local</url>
<name>CDH Releases Repository</name>
</repository>
<snapshotRepository>
@@ -114,6 +114,36 @@
</plugins>
</build>
</profile>
<profile>
<!-- profile to use with Atlassian Clover for code coverage -->
<id>clover</id>
<properties>
<clover.version>4.0.3</clover.version>
<clover.generateHtml>true</clover.generateHtml>
<clover.generateXml>true</clover.generateXml>
</properties>
<dependencies>
<dependency>
<groupId>com.atlassian.clover</groupId>
<artifactId>clover</artifactId>
<version>${clover.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<!-- Clover plugin to enable maven to create instantiated jars that will record code coverage -->
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>maven-clover2-plugin</artifactId>
<version>${clover.version}</version>
<configuration>
<generateHtml>${clover.generateHtml}</generateHtml>
<generateXml>${clover.generateXml}</generateXml>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>

<build>
@@ -153,7 +183,7 @@
<pattern>com.</pattern>
<shadedPattern>${privateClassPath}.com.</shadedPattern>
<includes>
<include>com.google.guava.**</include>
<include>com.google.common.**</include>
<include>com.fasterxml.jackson.**</include>
</includes>
</relocation>
@@ -209,7 +239,6 @@
<additionalparam>${javadocOptions}</additionalparam>
<docfilessubdirs>true</docfilessubdirs>
<outputDirectory>${project.build.directory}/javadoc</outputDirectory>
<stylesheetfile>${basedir}/src/javadoc/javadoc.css</stylesheetfile>
<overview>${basedir}/src/javadoc/overview.html</overview>
<doctitle>Cloudera Manager API (${project.version})</doctitle>
<windowtitle>Cloudera Manager API (${project.version})</windowtitle>
@@ -237,6 +266,11 @@
<excludeFilterFile>findbugs-exclude.xml</excludeFilterFile>
</configuration>
</plugin>
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>1.4.3</version>
</plugin>
</plugins>
</build>
<dependencies>
607 changes: 0 additions & 607 deletions java/src/javadoc/javadoc.css

This file was deleted.

37 changes: 36 additions & 1 deletion java/src/main/java/com/cloudera/api/ApiRootResource.java
Original file line number Diff line number Diff line change
@@ -16,6 +16,12 @@
package com.cloudera.api;

import com.cloudera.api.v1.RootResourceV1;
import com.cloudera.api.v10.RootResourceV10;
import com.cloudera.api.v11.RootResourceV11;
import com.cloudera.api.v12.RootResourceV12;
import com.cloudera.api.v13.RootResourceV13;
import com.cloudera.api.v14.RootResourceV14;
import com.cloudera.api.v15.RootResourceV15;
import com.cloudera.api.v2.RootResourceV2;
import com.cloudera.api.v3.RootResourceV3;
import com.cloudera.api.v4.RootResourceV4;
@@ -24,7 +30,6 @@
import com.cloudera.api.v7.RootResourceV7;
import com.cloudera.api.v8.RootResourceV8;
import com.cloudera.api.v9.RootResourceV9;
import com.cloudera.api.v10.RootResourceV10;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@@ -101,6 +106,36 @@ public interface ApiRootResource {
@Path("/v10")
RootResourceV10 getRootV10();

/**
* @return The v11 root resource.
*/
@Path("/v11")
RootResourceV11 getRootV11();

/**
* @return The v12 root resource.
*/
@Path("/v12")
RootResourceV12 getRootV12();

/**
* @return The v13 root resource.
*/
@Path("/v13")
RootResourceV13 getRootV13();

/**
* @return The v14 root resource.
*/
@Path("/v14")
RootResourceV14 getRootV14();

/**
* @return The v15 root resource.
*/
@Path("/v15")
RootResourceV15 getRootV15();

/**
* Fetch the current API version supported by the server.
* <p>
11 changes: 11 additions & 0 deletions java/src/main/java/com/cloudera/api/ApiUtils.java
Original file line number Diff line number Diff line change
@@ -135,6 +135,17 @@ public static void checkOffsetAndLimit(int offset, int limit) {
"Limit should be greater than 0.");
}


/**
* Check that the given limit is positive.
*
* @param limit Value to use as limit of a list's size.
*/
public static void checkLimit(int limit) {
Preconditions.checkArgument(limit > 0,
"Limit should be greater than 0.");
}

private ApiUtils() { }

}
Original file line number Diff line number Diff line change
@@ -35,13 +35,16 @@
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.Client;
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.message.Message;
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;
public static final TimeUnit DEFAULT_CONNECTION_TIMEOUT_UNITS =
@@ -53,8 +56,8 @@ public class ClouderaManagerClientBuilder {
private URL baseUrl;
private String hostname;
private int port = DEFAULT_TCP_PORT;
private boolean enableTLS = false;
private boolean enableLogging = false;
private boolean enableTLS;
private boolean enableLogging;
private String username;
private String password;
private long connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;
@@ -63,7 +66,11 @@ public class ClouderaManagerClientBuilder {
private TimeUnit receiveTimeoutUnits = DEFAULT_RECEIVE_TIMEOUT_UNITS;
private boolean validateCerts = true;
private boolean validateCn = true;
private TrustManager[] trustManagers = null;
private boolean threadSafe;
private boolean maintainSessionAcrossRequests;
private boolean streamAutoClosure;
private TrustManager[] trustManagers;
private String acceptLanguage;

/**
* Cache JAXRSClientFactoryBean per proxyType.
@@ -97,6 +104,12 @@ public JAXRSClientFactoryBean load(Class<?> proxyType) throws Exception {
}
});

public ClouderaManagerClientBuilder withAcceptLanguage(
String acceptLaunguage) {
this.acceptLanguage = acceptLaunguage;
return this;
}

public ClouderaManagerClientBuilder withBaseURL(URL baseUrl) {
this.baseUrl = baseUrl;
return this;
@@ -122,6 +135,28 @@ public ClouderaManagerClientBuilder enableLogging() {
return this;
}

/**
* @param threadSafe Set if to create a thread safe client.
* @return
*/
public ClouderaManagerClientBuilder setThreadSafe(boolean threadSafe) {
this.threadSafe = threadSafe;
return this;
}

/**
* @param maintainSessionAcrossRequests If set to true, created client will
* maintain HTTP session across multiple requests. Setting this to true also
* means that login attempt will be made for the 1st request for a new client
* or when the previous session has time out.
* @return
*/
public ClouderaManagerClientBuilder setMaintainSessionAcrossRequests(
boolean maintainSessionAcrossRequests) {
this.maintainSessionAcrossRequests = maintainSessionAcrossRequests;
return this;
}

public ClouderaManagerClientBuilder withUsernamePassword(String username,
String password) {
this.username = username;
@@ -155,6 +190,18 @@ public ClouderaManagerClientBuilder disableTlsCnValidation() {
return this;
}

/**
* By default, ClouderaManagerClientBuilder disables auto-closure of response
* streams when generated client are making requests. This method enables
* this. If this is not enabled, caller of the client is responsible for
* closing the response streams.
* @return ClouderaManagerClientBuilder
*/
public ClouderaManagerClientBuilder enableStreamAutoClosure() {
this.streamAutoClosure = true;
return this;
}

@VisibleForTesting
String generateAddress() {
final String apiRootPath = "api/";
@@ -220,11 +267,21 @@ protected <T> T build(Class<T> proxyType) {
if (enableLogging) {
bean.setFeatures(Arrays.<AbstractFeature>asList(new LoggingFeature()));
}
bean.setThreadSafe(threadSafe);
rootResource = bean.create(proxyType);
}

boolean isTlsEnabled = address.startsWith("https://");
ClientConfiguration config = WebClient.getConfig(rootResource);
if (maintainSessionAcrossRequests) {
config.getRequestContext().put(Message.MAINTAIN_SESSION,
Boolean.TRUE);
}
if (streamAutoClosure) {
config.getRequestContext().put("response.stream.auto.close",
Boolean.TRUE);
}

HTTPConduit conduit = (HTTPConduit) config.getConduit();
if (isTlsEnabled) {
TLSClientParameters tlsParams = new TLSClientParameters();
@@ -239,6 +296,9 @@ else if (trustManagers != null) {
}

HTTPClientPolicy policy = conduit.getClient();
if (acceptLanguage != null) {
policy.setAcceptLanguage(acceptLanguage);
}
policy.setConnectionTimeout(
connectionTimeoutUnits.toMillis(connectionTimeout));
policy.setReceiveTimeout(
@@ -249,26 +309,24 @@ else if (trustManagers != null) {
private static JAXRSClientFactoryBean cleanFactory(JAXRSClientFactoryBean bean) {
bean.setUsername(null);
bean.setPassword(null);
bean.setInitialState(null);
bean.setFeatures(Arrays.<AbstractFeature>asList());
return bean;
}

/**
* Closes the transport level conduit in the client. Reopening a new
* connection, requires creating a new client object using the build()
* method in this builder.
* Releases the internal state and configuration associated with this client.
* Reopening a new connection requires creating a new client object using the
* build() method in this builder.
*
* @param root The resource returned by the build() method of this
* builder class
*/
public static void closeClient(ApiRootResource root) {
ClientConfiguration config = WebClient.getConfig(root);
HTTPConduit conduit = config.getHttpConduit();
if (conduit == null) {
throw new IllegalArgumentException(
"Client is not using the HTTP transport");
Client client = WebClient.client(root);
if (client != null) {
client.close();
}
conduit.close();
}

/**
@@ -289,14 +347,17 @@ public static void clearCachedResources() {
/** A trust manager that will accept all certificates. */
private static class AcceptAllTrustManager implements X509TrustManager {

@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
// no op.
}

@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
// no op.
}

@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
6 changes: 6 additions & 0 deletions java/src/main/java/com/cloudera/api/DataView.java
Original file line number Diff line number Diff line change
@@ -21,6 +21,12 @@
public enum DataView {
SUMMARY,
FULL,
/**
* Entities with health test results and health test explanation.
* Generating and transferring health check explanation for entities can be
* very expensive.
**/
FULL_WITH_HEALTH_CHECK_EXPLANATION,
EXPORT,
/** All passwords and other sensitive fields are marked as REDACTED. */
EXPORT_REDACTED;
8 changes: 8 additions & 0 deletions java/src/main/java/com/cloudera/api/Parameters.java
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ public final class Parameters {
static public final String USER_NAME = "userName";
static public final String ACTIVITY_ID = "activityId";
static public final String PEER_NAME = "peerName";
static public final String PEER_TYPE = "type";
static public final String SCHEDULE_ID = "scheduleId";
static public final String PRODUCT = "product";
static public final String VERSION = "version";
@@ -45,6 +46,11 @@ public final class Parameters {
static public final String MUST_USE_DESIRED_ROLLUP = "mustUseDesiredRollup";
static public final String FILTER = "filter";
static public final String COMMAND_NAME = "commandName";
static public final String DIR_PATH = "directoryPath";
static public final String EXTERNAL_ACCOUNT_NAME = "name";
static public final String EXTERNAL_ACCOUNT_TYPE_NAME = "typeName";
static public final String EXTERNAL_ACCOUNT_CATEGORY_NAME = "categoryName";
static public final String DISPLAY_NAME = "displayName";

/* Common query params. */
static public final String FROM = "from";
@@ -57,9 +63,11 @@ public final class Parameters {
/* Default values. */
static public final String DATA_VIEW_DEFAULT = "summary";
static public final String DATA_VIEW_EXPORT = "export";
static public final String DATA_VIEW_FULL = "full";
static public final String DATE_TIME_NOW = "now";
static public final String DAILY_AGGREGATION = "daily";
static public final String FILTER_DEFAULT = "";
static public final String ROLLUP_DEFAULT = "RAW";

/* Common filtering properties. */
static public final String HOSTNAME = "hostname";
50 changes: 47 additions & 3 deletions java/src/main/java/com/cloudera/api/model/ApiCluster.java
Original file line number Diff line number Diff line change
@@ -33,18 +33,22 @@
*/
@XmlRootElement(name = "cluster")
@XmlType(propOrder = {"name", "displayName", "version", "fullVersion",
"maintenanceMode", "maintenanceOwners", "services", "parcels", "clusterUrl"})
"maintenanceMode", "maintenanceOwners", "services", "parcels", "clusterUrl",
"hostsUrl", "entityStatus", "uuid"})
public class ApiCluster {

private String name;
private String displayName;
private String uuid;
private String clusterUrl;
private String hostsUrl;
private ApiClusterVersion version;
private String fullVersion;
private Boolean maintenanceMode;
private List<ApiEntityType> maintenanceOwners;
private List<ApiService> services;
private List<ApiParcel> parcels;
private ApiEntityStatus entityStatus;

public ApiCluster() {
// For JAX-B
@@ -102,8 +106,21 @@ public void setDisplayName(String displayName) {
}

/**
* Read only.
* Link into the Cloudera Manager web UI for this specific cluster.
* Readonly. The UUID of the cluster.
* <p>
* Available since API v15.
*/
@XmlElement
public String getUuid() {
return uuid;
}

public void setUuid(String uuid) {
this.uuid = uuid;
}

/**
* Readonly. Link into the Cloudera Manager web UI for this specific cluster.
* <p>
* Available since API v10.
*/
@@ -116,6 +133,20 @@ public void setClusterUrl(String clusterUrl) {
this.clusterUrl = clusterUrl;
}

/**
* Readonly. Link into the Cloudera Manager web UI for host table for this cluster.
* <p>
* Available since API v11.
*/
@XmlElement
public String getHostsUrl() {
return hostsUrl;
}

public void setHostsUrl(String hostsUrl) {
this.hostsUrl = hostsUrl;
}

/** The CDH version of the cluster. */
@XmlElement
public ApiClusterVersion getVersion() {
@@ -193,4 +224,17 @@ public List<ApiParcel> getParcels() {
public void setParcels(List<ApiParcel> parcels) {
this.parcels = parcels;
}

/**
* Readonly. The entity status for this cluster.
* Available since API v11.
*/
@XmlElement
public ApiEntityStatus getEntityStatus() {
return entityStatus;
}

public void setEntityStatus(ApiEntityStatus entityStatus) {
this.entityStatus = entityStatus;
}
}
137 changes: 137 additions & 0 deletions java/src/main/java/com/cloudera/api/model/ApiClusterTemplate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// 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.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.google.common.collect.Lists;

import java.util.List;

import javax.xml.bind.annotation.XmlRootElement;

/**
* Details of cluster template
*/

@XmlRootElement(name = "clusterTemplate")
@JsonInclude(Include.NON_EMPTY)
public class ApiClusterTemplate {

/**
* CDH version
*/
private String cdhVersion;
/**
* Cluster display name
*/
private String displayName;
/**
* CM version for which the template
*/
private String cmVersion;
/**
* List of all repositories registered with CM
*/
@JsonInclude(Include.NON_EMPTY)
private List<String> repositories = Lists.newArrayList();
/**
* All the parcels that needs to be deployed and activated
*/
private List<ApiProductVersion> products = Lists.newArrayList();
/**
* All the services that needs to be deployed
*/
@JsonInclude(Include.NON_EMPTY)
private List<ApiClusterTemplateService> services = Lists.newArrayList();
/**
* All host templates
*/
@JsonInclude(Include.NON_EMPTY)
private List<ApiClusterTemplateHostTemplate> hostTemplates = Lists.newArrayList();

/**
* A constructor listing all the variables and references that needs to be
* resolved for this template
*/
private ApiClusterTemplateInstantiator instantiator;

public String getCdhVersion() {
return this.cdhVersion;
}

public void setCdhVersion(String cdhVersion) {
this.cdhVersion = cdhVersion;
}

public List<ApiProductVersion> getProducts() {
return this.products;
}

public void setProducts(List<ApiProductVersion> products) {
this.products = products;
}

public List<ApiClusterTemplateService> getServices() {
return this.services;
}

public void setServices(List<ApiClusterTemplateService> services) {
this.services = services;
}

public List<ApiClusterTemplateHostTemplate> getHostTemplates() {
return this.hostTemplates;
}

public void setHostTemplates(List<ApiClusterTemplateHostTemplate> hostTemplates) {
this.hostTemplates = hostTemplates;
}

public String getDisplayName() {
return this.displayName;
}

public void setDisplayName(String displayName) {
this.displayName = displayName;
}

public String getCmVersion() {
return this.cmVersion;
}

public void setCmVersion(String cmVersion) {
this.cmVersion = cmVersion;
}

public ApiClusterTemplateInstantiator getInstantiator() {
return this.instantiator;
}

public void setInstantiator(ApiClusterTemplateInstantiator instantiator) {
this.instantiator = instantiator;
}

public List<String> getRepositories() {
return this.repositories;
}

public void setRepositories(List<String> repositories) {
this.repositories = repositories;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// 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.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

/**
* Config Details: The config can either have a value or ref or variable.
*/
public class ApiClusterTemplateConfig {
/**
* Config name
*/
private String name;
/**
* Config value
*/
@JsonInclude(Include.NON_NULL)
private String value;
/**
* Name of the reference. If referring to a service then it will be replaced
* with actual service name at import time. If referring to a role then it
* will be replaced with the host name containing that role at import time.
*/
@JsonInclude(Include.NON_EMPTY)
private String ref;
/**
* Referring a variable. The variable value will be provided by the user at
* import time. Variable name for this config. At import time the value of
* this variable will be provided by the
* {@link #ApiClusterTemplateInstantiator.Variable}
*/
@JsonInclude(Include.NON_EMPTY)
private String variable;
/**
* This indicates that the value was automatically configured.
*/
@JsonInclude(Include.NON_DEFAULT)
private boolean autoConfig;

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public String getValue() {
return this.value;
}

public void setValue(String value) {
this.value = value;
}

public String getRef() {
return this.ref;
}

public void setRef(String ref) {
this.ref = ref;
}

public String getVariable() {
return this.variable;
}

public void setVariable(String variable) {
this.variable = variable;
}

public boolean isAutoConfig() {
return this.autoConfig;
}

public void setAutoConfig(boolean autoConfig) {
this.autoConfig = autoConfig;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// 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.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.google.common.collect.Sets;

import java.util.Set;

/**
* This contains information about the host or host range on which provided
* host template will be applied.
*/
@JsonInclude(Include.NON_EMPTY)
public class ApiClusterTemplateHostInfo {
/**
* Host name
*/
private String hostName;
/**
* Host range. Either this this or host name must be provided.
*/
private String hostNameRange;
/**
* Rack Id
*/
private String rackId;
/**
* Pointing to the host template reference in the cluster template.
*/
private String hostTemplateRefName;
/**
* This will used to resolve the roles defined in the cluster template. This
* roleRefName will be used to connect this host with that a role referrence
* defined in cluster template.
*/
private Set<String> roleRefNames = Sets.newHashSet();

public String getHostName() {
return this.hostName;
}

public ApiClusterTemplateHostInfo setHostName(String hostName) {
this.hostName = hostName;
return this;
}

public String getHostNameRange() {
return this.hostNameRange;
}

public void setHostNameRange(String hostNameRange) {
this.hostNameRange = hostNameRange;
}

public String getRackId() {
return this.rackId;
}

public void setRackId(String rackId) {
this.rackId = rackId;
}

public String getHostTemplateRefName() {
return this.hostTemplateRefName;
}

public void setHostTemplateRefName(String hostTemplateRefName) {
this.hostTemplateRefName = hostTemplateRefName;
}

public Set<String> getRoleRefNames() {
return this.roleRefNames;
}

public void setRoleRefNames(Set<String> roleRefNames) {
this.roleRefNames = roleRefNames;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// 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.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.google.common.collect.Lists;

import java.util.List;

/**
* Host templates will contain information about the role config groups that
* should be applied to a host. This basically means a host will have a role
* corresponding to each config group.
*/
@JsonInclude(Include.NON_EMPTY)
public class ApiClusterTemplateHostTemplate {
/**
* Reference name
*/
private String refName;
/**
* Represent the cardinality of this host template on source
*/
private int cardinality;
/**
* List of role config groups
*/
private List<String> roleConfigGroupsRefNames = Lists.newArrayList();

public String getRefName() {
return this.refName;
}

public void setRefName(String refName) {
this.refName = refName;
}

public List<String> getRoleConfigGroupsRefNames() {
return this.roleConfigGroupsRefNames;
}

public void setRoleConfigGroupsRefNames(
List<String> roleConfigGroupsRefNames) {
this.roleConfigGroupsRefNames = roleConfigGroupsRefNames;
}

public int getCardinality() {
return this.cardinality;
}

public void setCardinality(int cardinality) {
this.cardinality = cardinality;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// 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.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.google.common.collect.Lists;

import java.util.List;

import javax.xml.bind.annotation.XmlRootElement;

/**
* Details of cluster template
*/

@XmlRootElement(name = "clusterTemplateInstantiator")
@JsonInclude(Include.NON_EMPTY)
public class ApiClusterTemplateInstantiator {

/**
* Cluster name
*/
private String clusterName;
/**
* All the hosts that are part of that cluster
*/
private List<ApiClusterTemplateHostInfo> hosts = Lists.newArrayList();
/**
* All the variables the are referred by the cluster template
*/
private List<ApiClusterTemplateVariable> variables = Lists.newArrayList();
/**
* All the role config group informations for non-base RCGs.
*/
private List<ApiClusterTemplateRoleConfigGroupInfo> roleConfigGroups = Lists.newArrayList();

public String getClusterName() {
return this.clusterName;
}

public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}

public List<ApiClusterTemplateHostInfo> getHosts() {
return this.hosts;
}

public void setHosts(List<ApiClusterTemplateHostInfo> hosts) {
this.hosts = hosts;
}

public List<ApiClusterTemplateVariable> getVariables() {
return this.variables;
}

public void setVariables(
List<ApiClusterTemplateVariable> variables) {
this.variables = variables;
}

public List<ApiClusterTemplateRoleConfigGroupInfo> getRoleConfigGroups() {
return roleConfigGroups;
}

public void setRoleConfigGroups(
List<ApiClusterTemplateRoleConfigGroupInfo> roleConfigGroups) {
this.roleConfigGroups = roleConfigGroups;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// 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.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

/**
* Role info: This will contain information related to a role referred by some
* configuration. During import type this role must be materizalized.
*
*/
@JsonInclude(Include.NON_EMPTY)
public class ApiClusterTemplateRole {
/**
* Role reference name
*/
private String refName;
/**
* Role type
*/
private String roleType;

public String getRefName() {
return this.refName;
}

public void setRefName(String refName) {
this.refName = refName;
}

public String getRoleType() {
return this.roleType;
}

public void setRoleType(String roleType) {
this.roleType = roleType;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// 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.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.google.common.collect.Lists;

import java.util.List;

/**
* Role config group info.
*/
@JsonInclude(Include.NON_EMPTY)
public class ApiClusterTemplateRoleConfigGroup {
/**
* The reference name of the role config.
*/
private String refName;
/**
* Role type
*/
private String roleType;
/**
* If true then it is the base config group for that role. There can only be
* one base role config group for a given role type.
*/
@JsonInclude(Include.NON_DEFAULT)
private boolean isBase;
/**
* Role config group display name
*/
private String displayName;
/**
* List of configurations
*/
private List<ApiClusterTemplateConfig> configs = Lists.newArrayList();

public String getRefName() {
return this.refName;
}

public void setRefName(String refName) {
this.refName = refName;
}

public String getRoleType() {
return this.roleType;
}

public void setRoleType(String roleType) {
this.roleType = roleType;
}

public boolean isBase() {
return this.isBase;
}

public void setBase(boolean isBase) {
this.isBase = isBase;
}

public String getDisplayName() {
return this.displayName;
}

public void setDisplayName(String displayName) {
this.displayName = displayName;
}

public List<ApiClusterTemplateConfig> getConfigs() {
return this.configs;
}

public void setConfigs(List<ApiClusterTemplateConfig> configs) {
this.configs = configs;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// 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;


/**
* During import time information related to all the non-base config groups
* must be provided.
*/
public class ApiClusterTemplateRoleConfigGroupInfo {
/**
* Role config group reference name. This much match the reference name from
* the template.
*/
private String rcgRefName;
/**
* Role config group name.
*/
private String name;

public String getRcgRefName() {
return this.rcgRefName;
}

public void setRcgRefName(String rcgRefName) {
this.rcgRefName = rcgRefName;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// 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.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.google.common.collect.Lists;

import java.util.List;

/**
* Service information
*/
@JsonInclude(Include.NON_EMPTY)
public class ApiClusterTemplateService {
/**
* Reference name of the service. This could be referred by some
* configuration.
*/
private String refName;
/**
* Service type
*/
private String serviceType;
/**
* Service level configuration
*/
private List<ApiClusterTemplateConfig> serviceConfigs = Lists.newArrayList();
/**
* All role config groups for that service
*/
private List<ApiClusterTemplateRoleConfigGroup> roleConfigGroups = Lists.newArrayList();
/**
* Service display name.
*/
private String displayName;
/**
* List of roles for this service that are referred by some configuration.
*/
private List<ApiClusterTemplateRole> roles = Lists.newArrayList();

public String getRefName() {
return this.refName;
}

public void setRefName(String refName) {
this.refName = refName;
}

public String getServiceType() {
return this.serviceType;
}

public void setServiceType(String serviceType) {
this.serviceType = serviceType;
}

public List<ApiClusterTemplateConfig> getServiceConfigs() {
return this.serviceConfigs;
}

public void setServiceConfigs(List<ApiClusterTemplateConfig> serviceConfigs) {
this.serviceConfigs = serviceConfigs;
}

public List<ApiClusterTemplateRoleConfigGroup> getRoleConfigGroups() {
return this.roleConfigGroups;
}

public void setRoleConfigGroups(List<ApiClusterTemplateRoleConfigGroup> roleConfigGroups) {
this.roleConfigGroups = roleConfigGroups;
}

public List<ApiClusterTemplateRole> getRoles() {
return this.roles;
}

public void setRoles(List<ApiClusterTemplateRole> roles) {
this.roles = roles;
}

public String getDisplayName() {
return this.displayName;
}

public void setDisplayName(String displayName) {
this.displayName = displayName;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// 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.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

/**
* Variable that is referred in cluster template.
*/
@JsonInclude(Include.NON_EMPTY)
public class ApiClusterTemplateVariable {
/**
* Variable name that are referred in cluster template
*/
private String name;
/**
* This value will be placed whereever the variable is referred in the
* cluster template
*/
private String value;

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public String getValue() {
return this.value;
}

public void setValue(String value) {
this.value = value;
}
}
107 changes: 95 additions & 12 deletions java/src/main/java/com/cloudera/api/model/ApiCmPeer.java
Original file line number Diff line number Diff line change
@@ -24,22 +24,34 @@
/**
* Information about a Cloudera Manager peer instance.
* <p>
* The <i>username</i> and <i>password</i> properties are only used when
* creating peers. They should be the credentials of a user with administrator
* privileges on the remote Cloudera Manager being linked. These credentials are
* not stored; they're just used to create the peer.
* The requirement and usage of <i>username</i> and <i>password</i> properties
* are dependent on the <i>clouderaManagerCreatedUser</i> flag.
* <p>
* When retrieving peer information, neither of the above fields are populated.
* When creating peers, if 'clouderaManagerCreatedUser' is true, the
* username/password should be the credentials of a user with administrator
* privileges on the remote Cloudera Manager. These credentials are not stored,
* they are used to connect to the peer and create a user in that peer. The
* newly created user is stored and used for communication with that peer.
* If 'clouderaManagerCreatedUser' is false, which is not applicable to
* REPLICATION peer type, the username/password to the remote Cloudera Manager
* are directly stored and used for all communications with that peer.
* <p>
* When updating peers, if 'clouderaManagerCreatedUser' is true and
* username/password are set, a new remote user will be created. If
* 'clouderaManagerCreatedUser' is false and username/password are set, the
* stored username/password will be updated.
*/
@XmlRootElement(name = "cmPeer")
public class ApiCmPeer {

private String name;
private ApiCmPeerType type;
private String url;
private String username;
private String password;
private Boolean clouderaManagerCreatedUser;

/** The name of the link. */
/** The name of the remote CM instance. Immutable during update.*/
@XmlElement
public String getName() {
return name;
@@ -49,7 +61,21 @@ public void setName(String name) {
this.name = name;
}

/** The URL of the remote CM instance. */
/**
* The type of the remote CM instance. Immutable during update.
*
* Available since API v11.
**/
@XmlElement
public ApiCmPeerType getType() {
return type;
}

public void setType(ApiCmPeerType type) {
this.type = type;
}

/** The URL of the remote CM instance. Mutable during update.*/
@XmlElement
public String getUrl() {
return url;
@@ -59,7 +85,22 @@ public void setUrl(String url) {
this.url = url;
}

/** The remote admin username, for setting up the link. */
/**
* When creating peers, if 'clouderaManagerCreatedUser' is true, this should be
* the remote admin username for creating a user in remote Cloudera Manager. The
* created remote user will then be stored in the local Cloudera Manager DB and
* used in later communication. If 'clouderaManagerCreatedUser' is false, which
* is not applicable to REPLICATION peer type, Cloudera Manager will store this
* username in the local DB directly and use it together with 'password' for
* communication.
*
* Mutable during update.
* When set during update, if 'clouderaManagerCreatedUser' is true, a new user
* in remote Cloudera Manager is created, the newly created remote user will be
* stored in the local DB. An attempt to delete the previously created remote
* user will be made; If 'clouderaManagerCreatedUser' is false, the
* username/password in the local DB will be updated.
**/
@XmlElement
public String getUsername() {
return username;
@@ -69,7 +110,22 @@ public void setUsername(String username) {
this.username = username;
}

/** The remote admin password, for setting up the link. */
/**
* When creating peers, if 'clouderaManagerCreatedUser' is true, this should be
* the remote admin password for creating a user in remote Cloudera Manager. The
* created remote user will then be stored in the local Cloudera Manager DB and
* used in later communication. If 'clouderaManagerCreatedUser' is false, which
* is not applicable to REPLICATION peer type, Cloudera Manager will store this
* password in the local DB directly and use it together with 'username' for
* communication.
*
* Mutable during update.
* When set during update, if 'clouderaManagerCreatedUser' is true, a new user
* in remote Cloudera Manager is created, the newly created remote user will be
* stored in the local DB. An attempt to delete the previously created remote
* user will be made; If 'clouderaManagerCreatedUser' is false, the
* username/password in the local DB will be updated.
**/
@XmlElement
public String getPassword() {
return password;
@@ -79,11 +135,36 @@ public void setPassword(String password) {
this.password = password;
}

/**
* If true, Cloudera Manager creates a remote user using the given
* username/password and stores the created user in local DB for use in later
* communication. Cloudera Manager will also try to delete the created remote
* user when deleting such peers.
*
* If false, Cloudera Manager will store the provided username/password in
* the local DB and use them in later communication. 'false' value on this
* field is not applicable to REPLICATION peer type.
*
* Available since API v11.
*
* Immutable during update. Should not be set when updating peers.
**/
@XmlElement
public Boolean getClouderaManagerCreatedUser() {
return clouderaManagerCreatedUser;
}

public void setClouderaManagerCreatedUser(Boolean clouderaManagerCreatedUser) {
this.clouderaManagerCreatedUser = clouderaManagerCreatedUser;
}

@Override
public String toString() {
return Objects.toStringHelper(this)
.add("name", name)
.add("url", url)
.add("type", type)
.add("clouderaManagerCreatedUser", clouderaManagerCreatedUser)
.toString();
}

@@ -92,12 +173,14 @@ public boolean equals(Object o) {
ApiCmPeer other = ApiUtils.baseEquals(this, o);
return this == other || (other != null &&
Objects.equal(name, other.getName()) &&
Objects.equal(url, other.getUrl()));
Objects.equal(url, other.getUrl()) &&
Objects.equal(type, other.getType()) &&
Objects.equal(clouderaManagerCreatedUser,
other.getClouderaManagerCreatedUser()));
}

@Override
public int hashCode() {
return Objects.hashCode(name, url);
return Objects.hashCode(name, url, type, clouderaManagerCreatedUser);
}

}
24 changes: 24 additions & 0 deletions java/src/main/java/com/cloudera/api/model/ApiCmPeerType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// 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;

/**
* Enum for CM peer types.
*/
public enum ApiCmPeerType {
REPLICATION, // Remote CM is used in replication.
STATUS_AGGREGATION // Remote CM is used in status aggregation.
}
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ public class ApiCollectDiagnosticDataArguments {
private String ticketNumber;
private String comments;
private String clusterName;
private Boolean enableMonitorMetricsCollection;
private List<String> roles;

/**
@@ -48,17 +49,21 @@ public void setBundleSize(long bundleSizeByte) {
}

/**
* This parameter is ignored as of CM 4.5.
* Use endTime and bundleSize instead.
* This parameter is ignored between CM 4.5 and CM 5.7 versions.
* For versions from CM 4.5 to CM 5.7, use endTime and
* bundleSizeBytes instead.
*
* For CM 5.7+ versions, startTime is an optional parameter that
* is with endTime and bundleSizeBytes. This was introduced
* to perform diagnostic data estimation and collection of global
* diagnostics data for a certain time range.
* The start time (in ISO 8601 format)
* of the period to collection statistics for.
*/
@Deprecated
public String getStartTime() {
return startTime;
}

@Deprecated
public void setStartTime(String startTime) {
this.startTime = startTime;
}
@@ -120,6 +125,18 @@ public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}

/**
* Flag to enable collection of metrics for chart display.
*/
@XmlElement
public Boolean getEnableMonitorMetricsCollection() {
return enableMonitorMetricsCollection;
}

public void setEnableMonitorMetricsCollection(Boolean enable) {
this.enableMonitorMetricsCollection = enable;
}

/**
* List of roles for which to get logs and metrics.
*
40 changes: 35 additions & 5 deletions java/src/main/java/com/cloudera/api/model/ApiCommand.java
Original file line number Diff line number Diff line change
@@ -16,8 +16,10 @@
package com.cloudera.api.model;

import com.cloudera.api.ApiUtils;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.base.Objects;

import java.util.Arrays;
import java.util.Date;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@@ -40,7 +42,8 @@
@XmlType(propOrder = {
"id", "name", "startTime", "endTime",
"active", "success", "resultMessage", "resultDataUrl",
"clusterRef", "serviceRef", "roleRef", "hostRef", "parent", "children"
"clusterRef", "serviceRef", "roleRef", "hostRef", "parent", "children",
"canRetry"
})
public class ApiCommand {

@@ -59,19 +62,21 @@ public class ApiCommand {
private ApiHostRef hostRef;
private ApiCommandList children;
private ApiCommand parent;
private Boolean canRetry;

public ApiCommand() {
// For JAX-B
this(null, null, null, null, false, null, null, null, null, null, null, null,
null, null);
null, null, null);
}

public ApiCommand(Long id, String name, Date startTime, Date endTime,
boolean active, Boolean success, String resultMessage,
String resultDataUrl, ApiClusterRef clusterRef,
ApiServiceRef serviceRef,
ApiRoleRef roleRef, ApiHostRef hostRef,
ApiCommandList children, ApiCommand parent) {
ApiCommandList children, ApiCommand parent,
Boolean canRetry) {
this.id = id;
this.name = name;
this.startTime = startTime;
@@ -86,6 +91,7 @@ public ApiCommand(Long id, String name, Date startTime, Date endTime,
this.hostRef = hostRef;
this.children = children;
this.parent = parent;
this.canRetry = canRetry;
}

@Override
@@ -254,6 +260,29 @@ public void setChildren(ApiCommandList children) {
this.children = children;
}

/**
* Available since V11
*
* @deprecated Use {@link ApiCommand#getCanRetry()} instead
*/
@Deprecated
@JsonIgnore
public Boolean isCanRetry() {
return this.canRetry;
}

/**
* If the command can be retried. Available since V11
*/
@XmlElement
public Boolean getCanRetry() {
return this.canRetry;
}

public void setCanRetry(Boolean canRetry) {
this.canRetry = canRetry;
}

@Override
public boolean equals(Object o) {
ApiCommand that = ApiUtils.baseEquals(this, o);
@@ -270,14 +299,15 @@ public boolean equals(Object o) {
Objects.equal(roleRef, that.getRoleRef()) &&
Objects.equal(hostRef, that.getHostRef()) &&
Objects.equal(clusterRef, that.getClusterRef()) &&
Objects.equal(parent, that.getParent()));
Objects.equal(parent, that.getParent()) &&
Objects.equal(canRetry, that.getCanRetry()));
}

@Override
public int hashCode() {
return Objects.hashCode(id, name, startTime, endTime, active, success,
resultMessage, resultDataUrl, serviceRef, roleRef, hostRef, clusterRef,
parent);
parent, canRetry);
}

}
67 changes: 60 additions & 7 deletions java/src/main/java/com/cloudera/api/model/ApiConfig.java
Original file line number Diff line number Diff line change
@@ -33,9 +33,17 @@
* the default value (if any).
*/
@XmlRootElement(name = "config")
@XmlType(propOrder = { "name", "value", "required", "defaultValue",
"displayName", "description", "relatedName", "validationState",
"validationMessage" })
@XmlType(propOrder = { "name",
"value",
"required",
"defaultValue",
"displayName",
"description",
"relatedName",
"sensitive",
"validationState",
"validationMessage",
"validationWarningsSuppressed" })
public class ApiConfig {

private String name;
@@ -47,6 +55,8 @@ public class ApiConfig {
private Boolean required;
private ValidationState validationState;
private String validationMessage;
private Boolean validationWarningsSuppressed;
private Boolean sensitive;

public static enum ValidationState {
OK,
@@ -65,9 +75,16 @@ public static enum ValidationState {
* @param validationState State of the parameter's validation.
* @param validationMessage Message describing any validation issues.
*/
public ApiConfig(String name, String value, Boolean required,
String defaultValue, String displayName, String description,
String relatedName, ValidationState validationState, String validationMessage) {
public ApiConfig(
String name,
String value,
Boolean required,
String defaultValue,
String displayName,
String description,
String relatedName,
ValidationState validationState,
String validationMessage) {
this.name = name;
this.value = value;
this.required = required;
@@ -77,6 +94,7 @@ public ApiConfig(String name, String value, Boolean required,
this.relatedName = relatedName;
this.validationState = validationState;
this.validationMessage = validationMessage;
this.sensitive = null; // unset prior to v14
}

public ApiConfig(String name, String value) {
@@ -93,6 +111,8 @@ public ApiConfig() {
this.relatedName = null;
this.validationState = null;
this.validationMessage = null;
this.validationWarningsSuppressed = null;
this.sensitive = null;
}

public String toString() {
@@ -187,7 +207,7 @@ public void setName(String name) {

/**
* The user-defined value. When absent, the default value (if any)
* will be used.
* will be used. Can also be absent, when enumerating allowed configs.
*/
@XmlElement
public String getValue() {
@@ -238,4 +258,37 @@ public String getValidationMessage() {
public void setValidationMessage(String validationMessage) {
this.validationMessage = validationMessage;
}

/**
* Readonly. Requires "full" view.
* Whether validation warnings associated with this parameter are suppressed.
* In general, suppressed validation warnings are hidden in the Cloudera
* Manager UI. Configurations that do not produce warnings will not contain
* this field.
**/
@XmlElement
public Boolean getValidationWarningsSuppressed() {
return validationWarningsSuppressed;
}

public void setValidationWarningsSuppressed(
Boolean validationWarningsSuppressed) {
this.validationWarningsSuppressed = validationWarningsSuppressed;
}

/**
* Readonly.
* Whether this configuration is sensitive, i.e. contains information such as passwords, which
* might affect how the value of this configuration might be shared by the caller.
*
* Available since v14.
*/
@XmlElement
public Boolean getSensitive() {
return sensitive;
}

public void setSensitive(Boolean sensitive) {
this.sensitive = sensitive;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// 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 javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
* Arguments used to configure a cluster for Kerberos.
*/
@XmlRootElement(name="configureForKerberosArgs")
public class ApiConfigureForKerberosArguments {
private Long datanodeTransceiverPort;
private Long datanodeWebPort;

/**
* The HDFS DataNode transceiver port to use. This will be applied to all DataNode
* role configuration groups. If not specified, this will default to 1004.
*/
@XmlElement
public Long getDatanodeTransceiverPort() {
return datanodeTransceiverPort;
}

public void setDatanodeTransceiverPort(Long datanodeTransceiverPort) {
this.datanodeTransceiverPort = datanodeTransceiverPort;
}

/**
* The HDFS DataNode web port to use. This will be applied to all DataNode
* role configuration groups. If not specified, this will default to 1006.
*/
@XmlElement
public Long getDatanodeWebPort() {
return datanodeWebPort;
}

public void setDatanodeWebPort(Long datanodeWebPort) {
this.datanodeWebPort = datanodeWebPort;
}

@Override
public String toString() {
return Objects.toStringHelper(this)
.add("datanodeTransceiverPort", datanodeTransceiverPort)
.add("datanodeWebPort", datanodeWebPort)
.toString();
}

@Override
public boolean equals(Object o) {
ApiConfigureForKerberosArguments other = ApiUtils.baseEquals(this, o);
return this == other || (other != null &&
Objects.equal(this.datanodeTransceiverPort, other.datanodeTransceiverPort) &&
Objects.equal(this.datanodeWebPort, other.datanodeWebPort));
}

@Override
public int hashCode() {
return Objects.hashCode(datanodeTransceiverPort, datanodeWebPort);
}
}
53 changes: 53 additions & 0 deletions java/src/main/java/com/cloudera/api/model/ApiEntityStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// 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;

/**
* The single value used by the Cloudera Manager UI to represent the status of
* the entity. It is computed from a variety of other entity-specific states,
* not all values apply to all entities. For example, STARTING/STOPPING do not
* apply to a host.
*/
public enum ApiEntityStatus {
// There is not enough information to determine the entity status.
UNKNOWN,
// The entity in question does not have a entity status. For example, it is
// not something that can be running and it cannot have health.
NONE,
// The entity in question is not running, as expected.
STOPPED,
// The entity in question is not running, but it is expected to be running.
DOWN,
// The entity in question is running, but we do not have enough information
// to determine its health.
UNKNOWN_HEALTH,
// The entity in question is running, but all of its health checks are
// disabled.
DISABLED_HEALTH,
// The entity in question is running with concerning health.
CONCERNING_HEALTH,
// The entity in question is running with bad health.
BAD_HEALTH,
// The entity in question is running with good health.
GOOD_HEALTH,
// The entity in question is starting.
STARTING,
// The entity in question is stopping.
STOPPING,
// The application is in historical mode, and the entity in question does not
// have historical monitoring support.
HISTORY_NOT_AVAILABLE;
}
149 changes: 149 additions & 0 deletions java/src/main/java/com/cloudera/api/model/ApiExternalAccount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// 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.google.common.base.Objects;

import java.util.Date;

import javax.xml.bind.annotation.XmlRootElement;

/**
* Represents an instantiation of an external account type, referencing a supported
* external account type, via the typeName field, along with suitable configuration to
* access an external resource of the provided type.
*
* The typeName field must match the name of an external account type.
*/
@XmlRootElement(name="externalAccount")
public class ApiExternalAccount {
private String name;
private String displayName;
private Date createdTime;
private Date lastModifiedTime;
private String typeName;
private ApiConfigList accountConfigs;

public ApiExternalAccount() {
// For JAX-B
}

/**
* Represents the intial name of the account; used to uniquely identify this account.
*/
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

/**
* Represents a modifiable label to identify this account for user-visible purposes.
*/
public String getDisplayName() {
return displayName;
}

public void setDisplayName(String displayName) {
this.displayName = displayName;
}

/**
* Represents the time of creation for this account.
*/
public Date getCreatedTime() {
return createdTime;
}

public void setCreatedTime(Date createTime) {
this.createdTime = createTime;
}

/**
* Represents the last modification time for this account.
*/
public Date getLastModifiedTime() {
return lastModifiedTime;
}

public void setLastModifiedTime(Date lastModifiedTime) {
this.lastModifiedTime = lastModifiedTime;
}

/**
* Represents the Type ID of a supported external account type.
* The type represented by this field dictates which configuration options must be defined
* for this account.
*/
public String getTypeName() {
return typeName;
}

public void setTypeName(String typeName) {
this.typeName = typeName;
}

/**
* Represents the account configuration for this account.
*
* When an account is retrieved from the server,
* the configs returned must match allowed configuration for the type of this account.
*
* When specified for creation of a new account or for the update of an existing account,
* this field must include every required configuration parameter specified in the type's definition,
* with the account configuration's value field specified to represent the specific
* configuration desired for this account.
*/
public ApiConfigList getAccountConfigs() {
return accountConfigs;
}

public void setAccountConfigs(ApiConfigList accountConfigs) {
this.accountConfigs = accountConfigs;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ApiExternalAccount that = (ApiExternalAccount) o;
return Objects.equal(name, that.name) &&
Objects.equal(displayName, that.displayName) &&
Objects.equal(createdTime, that.createdTime) &&
Objects.equal(lastModifiedTime, that.lastModifiedTime) &&
Objects.equal(typeName, that.typeName) &&
Objects.equal(accountConfigs, that.accountConfigs);
}

@Override
public int hashCode() {
return Objects.hashCode(name, displayName, createdTime, lastModifiedTime, typeName, accountConfigs);
}

@Override
public String toString() {
return Objects.toStringHelper(this)
.add("name", name)
.add("typeName", typeName)
.add("createdTime", createdTime)
.add("lastModifiedTime", lastModifiedTime)
.add("displayName", displayName)
.add("accountConfigs", accountConfigs)
.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// 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;

/**
* Type representing an external account category.
*/
public class ApiExternalAccountCategory {
private String name;
private String displayName;
private String description;

/**
* Represents an identifier for a category.
*/
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

/**
* Represents a localized display name for a category.
*/
public String getDisplayName() {
return displayName;
}

public void setDisplayName(String displayName) {
this.displayName = displayName;
}

/**
* Represents a localized description for a category.
*/
public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}
}
Original file line number Diff line number Diff line change
@@ -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.model;

import java.util.List;

import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

/**
* Represents a list of external account categories.
*/
@XmlRootElement(name="externalAccountCategories")
public class ApiExternalAccountCategoryList extends ApiListBase<ApiExternalAccountCategory> {

public ApiExternalAccountCategoryList() {
// For JAX-B
super();
}

public ApiExternalAccountCategoryList(List<ApiExternalAccountCategory> values) {
super(values);
}

@XmlElementWrapper(name = ApiListBase.ITEMS_ATTR)
public List<ApiExternalAccountCategory> getExternalAccountCategories() {
return values;
}

public void setExternalAccountCategories(List<ApiExternalAccountCategory> values) {
this.values = values;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// 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 java.util.List;

import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

/**
* Represents a list of external accounts.
*/
@XmlRootElement(name="externalAccounts")
public class ApiExternalAccountList extends ApiListBase<ApiExternalAccount> {

public ApiExternalAccountList() {
super();
}

public ApiExternalAccountList(List<ApiExternalAccount> values) {
super(values);
}

@XmlElementWrapper(name = ApiListBase.ITEMS_ATTR)
public List<ApiExternalAccount> getExternalAccounts() {
return values;
}

public void setExternalAccountList(List<ApiExternalAccount> values) {
this.values = values;
}
}
109 changes: 109 additions & 0 deletions java/src/main/java/com/cloudera/api/model/ApiExternalAccountType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// 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 javax.xml.bind.annotation.XmlRootElement;

/**
* A supported external account type.
* An external account type represents an external authentication source that is used by
* Cloudera Manager in its APIs to take suitable actions that require authentication to an
* external service.
*
* An external account type is uniquely identified by a server-generated ID and identifies with
* a category identifier: e.g. The "AWS" category has an account type "AWS_Access_Key_Authorization"
*
*/
@XmlRootElement(name = "externalAccountType")
public class ApiExternalAccountType {

private String name;
private String categoryName;
private String type;
private String displayName;
private String description;
private ApiConfigList allowedAccountConfigs;

public ApiExternalAccountType() {
// For JAX-B
}

/**
* Represents the immutable name for this account.
*/
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

/**
* Represents the category of this account.
*/
public String getCategoryName() {
return categoryName;
}

public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}

/**
* Represents the type for this account.
*/
public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

/**
* Represents the localized display name for this account.
*/
public String getDisplayName() {
return displayName;
}

public void setDisplayName(String displayName) {
this.displayName = displayName;
}

/**
* Represents the localized description for this account type.
*/
public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

/**
* Represents the list of allowed account configs.
*/
public ApiConfigList getAllowedAccountConfigs() {
return allowedAccountConfigs;
}

public void setAllowedAccountConfigs(ApiConfigList allowedAccountConfigs) {
this.allowedAccountConfigs = allowedAccountConfigs;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// 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 java.util.List;

import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

// Types of external accounts supported - the list is dynamic, and can change/extend with
// CM versions without breaking API (though not behavior) backwards compatibility.

/**
* Represents a list of external account types.
*/
@XmlRootElement(name = "externalAccountTypes")
public class ApiExternalAccountTypeList extends ApiListBase<ApiExternalAccountType> {

public ApiExternalAccountTypeList() {
super();
}

public ApiExternalAccountTypeList(List<ApiExternalAccountType> values) {
super(values);
}

@XmlElementWrapper(name = ApiListBase.ITEMS_ATTR)
public List<ApiExternalAccountType> getExternalAccountTypes() {
return values;
}

public void setExternalAccountTypes(List<ApiExternalAccountType> values) {
this.values = values;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (c) 2016 Cloudera, Inc. All rights reserved.
package com.cloudera.api.model;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import com.cloudera.api.ApiUtils;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import org.apache.cxf.common.util.StringUtils;

@XmlRootElement(name = "hdfsCloudReplicationArguments")
public class ApiHdfsCloudReplicationArguments extends ApiHdfsReplicationArguments {

/**
* Source Account during replication. If this is non-null,
* destinationAccount should be null
*/
private String sourceAccount;

/**
* destination Account during replication. If this is non-null,
* sourceAccount should be null
*/
private String destinationAccount;

// For JAX-B
public ApiHdfsCloudReplicationArguments() {
}

public ApiHdfsCloudReplicationArguments(ApiServiceRef sourceService,
String sourcePath, String destinationPath,
String mapreduceServiceName, Integer numMaps, String userName,
String sourceAccount, String destinationAccount) {
super(sourceService, sourcePath, destinationPath, mapreduceServiceName,
numMaps, userName);
this.sourceAccount = sourceAccount;
this.destinationAccount = destinationAccount;
}

@XmlElement
public String getSourceAccount() {
return sourceAccount;
}

public void setSourceAccount(String sourceAccount) {
this.sourceAccount = sourceAccount;
}

@XmlElement
public String getDestinationAccount() {
return destinationAccount;
}

public void setDestinationAccount(String destinationAccount) {
this.destinationAccount = destinationAccount;
}

@Override
public String toString() {
if (!StringUtils.isEmpty(sourceAccount)) {
return super.toStringHelper()
.add("sourceAccount", sourceAccount)
.toString();
} else if (!StringUtils.isEmpty(destinationAccount)) {
return super.toStringHelper()
.add("destinationAccount", destinationAccount)
.toString();
}

Preconditions.checkState(false, "Both sourceAccount and destinationAccount are null " +
"in ApiHdfsCloudReplicationArguments");
return null;
}

@Override
public boolean equals(Object o) {
ApiHdfsCloudReplicationArguments other = ApiUtils.baseEquals(this, o);
return this == other || (other != null &&
super.equals(other) &&
Objects.equal(sourceAccount, other.sourceAccount) &&
Objects.equal(destinationAccount, other.destinationAccount));
}

@Override
public int hashCode() {
return Objects.hashCode(super.hashCode(), sourceAccount, destinationAccount);
}
}
Original file line number Diff line number Diff line change
@@ -15,11 +15,14 @@
// 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;

import com.cloudera.api.ApiUtils;
import com.google.common.base.Objects;

/**
* Replication arguments for HDFS.
@@ -45,6 +48,7 @@ public class ApiHdfsReplicationArguments {
private Boolean skipTrash;
private ReplicationStrategy replicationStrategy;
private Boolean preserveXAttrs;
private List<String> exclusionFilters;

/**
* The strategy for distributing the file replication tasks among the mappers
@@ -277,7 +281,7 @@ public void setSkipTrash(Boolean skipTrash) {
/**
* The strategy for distributing the file replication tasks among the mappers
* of the MR job associated with a replication. Default is
* {@link ReplicationStrategy.STATIC}.
* {@link ReplicationStrategy#STATIC}.
*/
@XmlElement
public ReplicationStrategy getReplicationStrategy() {
@@ -303,28 +307,47 @@ public void setPreserveXAttrs(Boolean preserveXAttrs) {
this.preserveXAttrs = preserveXAttrs;
}

/**
* Specify regular expression strings to match full paths of files and directories
* matching source paths and exclude them from the replication. Optional.
* Available since V11.
* @return exclusion paths, if set; null if no exclusion paths are specified.
*/
@XmlElement
public List<String> getExclusionFilters() {
return exclusionFilters;
}

public void setExclusionFilters(List<String> exclusionFilters) {
this.exclusionFilters = exclusionFilters;
}

protected Objects.ToStringHelper toStringHelper() {
return Objects.toStringHelper(this)
.add("sourceService", sourceService)
.add("sourcePath", sourcePath)
.add("destinationPath", destinationPath)
.add("mapreduceServiceName", mapreduceServiceName)
.add("schedulerPoolName", schedulerPoolName)
.add("numMaps", numMaps)
.add("dryRun", dryRun)
.add("bandwidthPerMap", bandwidthPerMap)
.add("abortOnError", abortOnError)
.add ("removeMissingFiles", removeMissingFiles)
.add("preserveReplicationCount", preserveReplicationCount)
.add("preserveBlockSize", preserveBlockSize)
.add("preservePermissions", preservePermissions)
.add("logPath", logPath)
.add("skipChecksumChecks", skipChecksumChecks)
.add("skipTrash", skipTrash)
.add("replicationStrategy", replicationStrategy)
.add("preserveXAttrs", preserveXAttrs)
.add("exclusionFilters", exclusionFilters);
}

@Override
public String toString() {
return Objects.toStringHelper(this)
.add("sourceService", sourceService)
.add("sourcePath", sourcePath)
.add("destinationPath", destinationPath)
.add("mapreduceServiceName", mapreduceServiceName)
.add("schedulerPoolName", schedulerPoolName)
.add("numMaps", numMaps)
.add("dryRun", dryRun)
.add("bandwidthPerMap", bandwidthPerMap)
.add("abortOnError", abortOnError)
.add ("removeMissingFiles", removeMissingFiles)
.add("preserveReplicationCount", preserveReplicationCount)
.add("preserveBlockSize", preserveBlockSize)
.add("preservePermissions", preservePermissions)
.add("logPath", logPath)
.add("skipChecksumChecks", skipChecksumChecks)
.add("skipTrash", skipTrash)
.add("replicationStrategy", replicationStrategy)
.add("preserveXAttrs", preserveXAttrs)
.toString();
return toStringHelper().toString();
}

@Override
@@ -348,7 +371,8 @@ public boolean equals(Object o) {
skipChecksumChecks == other.getSkipChecksumChecks() &&
Objects.equal(skipTrash, other.getSkipTrash()) &&
Objects.equal(replicationStrategy, other.getReplicationStrategy()) &&
Objects.equal(preserveXAttrs, other.getPreserveXAttrs()));
Objects.equal(preserveXAttrs, other.getPreserveXAttrs())) &&
Objects.equal(exclusionFilters, other.getExclusionFilters());
}

@Override
@@ -358,6 +382,6 @@ public int hashCode() {
bandwidthPerMap, abortOnError, removeMissingFiles,
preserveReplicationCount, preserveBlockSize, preservePermissions,
logPath, skipChecksumChecks, skipTrash, replicationStrategy,
preserveXAttrs);
preserveXAttrs, exclusionFilters);
}
}
Original file line number Diff line number Diff line change
@@ -48,6 +48,8 @@ public class ApiHdfsReplicationResult {
private String jobDetailsUri;
private boolean dryRun;
private List<String> snapshottedDirs;
private List<String> failedFiles;
private String runAsUser;

/** The file copy progress percentage. */
@XmlElement
@@ -257,6 +259,32 @@ public void setSnapshottedDirs(List<String> snapshottedDirs) {
this.snapshottedDirs = snapshottedDirs;
}

/**
* Returns run-as user name.
* Available since API v11.
*/
@XmlElement
public String getRunAsUser() {
return runAsUser;
}

public void setRunAsUser(String runAsUser) {
this.runAsUser = runAsUser;
}

/**
* The list of files that failed during replication.
* Available since API v11.
*/
@XmlElement
public List<String> getFailedFiles() {
return failedFiles;
}

public void setFailedFiles(List<String> failedFiles) {
this.failedFiles = failedFiles;
}

@Override
public boolean equals(Object o) {
ApiHdfsReplicationResult that = ApiUtils.baseEquals(this, o);
@@ -265,13 +293,15 @@ public boolean equals(Object o) {
Objects.equal(counters, that.getCounters()) &&
Objects.equal(setupError, that.getSetupError()) &&
dryRun == that.isDryRun() &&
Objects.equal(snapshottedDirs, that.getSnapshottedDirs()));
Objects.equal(snapshottedDirs, that.getSnapshottedDirs())) &&
Objects.equal(failedFiles, that.getFailedFiles()) &&
Objects.equal(runAsUser, that.getRunAsUser());
}

@Override
public int hashCode() {
return Objects.hashCode(progress, counters, setupError, dryRun,
snapshottedDirs);
snapshottedDirs, failedFiles, runAsUser);
}

@Override
@@ -282,6 +312,8 @@ public String toString() {
.add("setupError", setupError)
.add("dryRun", dryRun)
.add("snapshottedDirs", snapshottedDirs)
.add("failedFiles", failedFiles)
.add("runAsUser", runAsUser)
.toString();
}

42 changes: 42 additions & 0 deletions java/src/main/java/com/cloudera/api/model/ApiHealthCheck.java
Original file line number Diff line number Diff line change
@@ -19,10 +19,16 @@
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
* Represents a result from a health test performed by Cloudera Manager for an
* entity.
*/
@XmlRootElement(name = "healthCheck")
public class ApiHealthCheck {
private String name;
private ApiHealthSummary summary;
private String explanation;
private Boolean suppressed;

public ApiHealthCheck() {
// For JAX-B
@@ -33,6 +39,15 @@ public ApiHealthCheck(String name, ApiHealthSummary summary) {
this.summary = summary;
}

public ApiHealthCheck(String name,
ApiHealthSummary summary,
String explanation,
boolean suppressed) {
this(name, summary);
this.explanation = explanation;
this.suppressed = suppressed;
}

/** Unique name of this health check. */
@XmlElement
public String getName() {
@@ -52,4 +67,31 @@ public ApiHealthSummary getSummary() {
public void setSummary(ApiHealthSummary summary) {
this.summary = summary;
}

/**
* The explanation of this health check.
* Available since v11.
**/
@XmlElement
public String getExplanation() {
return explanation;
}

public void setExplanation(String explanation) {
this.explanation = explanation;
}

/**
* Whether this health test is suppressed. A suppressed health test is not
* considered when computing an entity's overall health.
* Available since v11.
**/
@XmlElement
public Boolean getSuppressed() {
return suppressed;
}

public void setSuppressed(Boolean suppressed) {
this.suppressed = suppressed;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// 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 com.google.common.base.Preconditions;
import org.apache.cxf.common.util.StringUtils;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "hiveCloudReplicationArguments")
public class ApiHiveCloudReplicationArguments extends ApiHiveReplicationArguments {

/**
* Source Account during replication. If this is non-null,
* destinationAccount should be null
*/
private String sourceAccount;

/**
* destination Account during replication. If this is non-null,
* sourceAccount should be null
*/
private String destinationAccount;

/**
* path at which data will be restored or backed up.
*/
private String cloudRootPath;

/**
* This will decide how cloud replication will take place
*/
public enum ReplicationOption {
// This is used for backup as well as restore operation,
// Use this, when you want to store/get only metadata to/from cloud
METADATA_ONLY,

// This is used for backup as well as restore operation,
// Use this, when you want to store/get complete metadata/data to/from cloud
METADATA_AND_DATA,

// This is used for restore operation only,
// Use this, when you want to get metadata and hive entities are pointing to
// data on cloud.
KEEP_DATA_IN_CLOUD
}

/**
* Decides the type of hive cloud replication.
*/
private ReplicationOption replicationOption;

public ApiHiveCloudReplicationArguments() {
// For JAX-B
}

@XmlElement
public String getSourceAccount() {
return sourceAccount;
}

public void setSourceAccount(String sourceAccount) {
this.sourceAccount = sourceAccount;
}

@XmlElement
public String getDestinationAccount() {
return destinationAccount;
}

public void setDestinationAccount(String destinationAccount) {
this.destinationAccount = destinationAccount;
}

public String getCloudRootPath() {
return cloudRootPath;
}

public void setCloudRootPath(String cloudRootPath) {
this.cloudRootPath = cloudRootPath;
}

public ReplicationOption getReplicationOption() {
return replicationOption;
}

public void setReplicationOption(ReplicationOption replicationOption) {
this.replicationOption = replicationOption;
}

@Override
public String toString() {
Objects.ToStringHelper stringHelper = super.toStringHelper();
if (!StringUtils.isEmpty(sourceAccount)) {
stringHelper.add("sourceAccount", sourceAccount);
} else if (!StringUtils.isEmpty(destinationAccount)) {
stringHelper.add("destinationAccount", destinationAccount);
}

stringHelper.add("cloudRootPath", cloudRootPath);
stringHelper.add("replicationOption", replicationOption);
return stringHelper.toString();
}

@Override
public boolean equals(Object o) {
ApiHiveCloudReplicationArguments other = ApiUtils.baseEquals(this, o);
return this == other || (other != null &&
super.equals(other) &&
Objects.equal(sourceAccount, other.sourceAccount) &&
Objects.equal(destinationAccount, other.destinationAccount) &&
Objects.equal(cloudRootPath, other.cloudRootPath) &&
Objects.equal(replicationOption, other.replicationOption));
}

@Override
public int hashCode() {
return Objects.hashCode(super.hashCode(), sourceAccount, destinationAccount,
cloudRootPath, replicationOption);
}
}
Original file line number Diff line number Diff line change
@@ -155,8 +155,7 @@ public void setDryRun(boolean dryRun) {
this.dryRun = dryRun;
}

@Override
public String toString() {
protected Objects.ToStringHelper toStringHelper() {
return Objects.toStringHelper(this)
.add("sourceService", sourceService)
.add("tableFilters", tableFilters)
@@ -165,8 +164,12 @@ public String toString() {
.add("replicateHdfs", replicateData)
.add("hdfsArguments", hdfsArguments)
.add("replicateImpalaMetadata", replicateImpalaMetadata)
.add("dryRun", dryRun)
.toString();
.add("dryRun", dryRun);
}

@Override
public String toString() {
return toStringHelper().toString();
}

@Override
Original file line number Diff line number Diff line change
@@ -30,6 +30,7 @@ public class ApiHiveReplicationError {
private String database;
private String tableName;
private String impalaUDF;
private String hiveUDF;
private String error;

public ApiHiveReplicationError() {
@@ -49,6 +50,16 @@ public ApiHiveReplicationError(String database, String tableName,
this.error = error;
}

public ApiHiveReplicationError(String database, String tableName,
String impalaUDF, String hiveUDF,
String error) {
this.database = database;
this.tableName = tableName;
this.impalaUDF = impalaUDF;
this.hiveUDF = hiveUDF;
this.error = error;
}

/** Name of the database. */
@XmlElement
public String getDatabase() {
@@ -79,6 +90,16 @@ public void setImpalaUDF(String impalaUDF) {
this.impalaUDF = impalaUDF;
}

/** Hive UDF signature, includes the UDF name and parameter types. */
@XmlElement
public String getHiveUDF() {
return hiveUDF;
}

public void setHiveUDF(String hiveUDF) {
this.hiveUDF = hiveUDF;
}

/** Description of the error. */
@XmlElement
public String getError() {
@@ -95,6 +116,7 @@ public String toString() {
.add("database", database)
.add("tableName", tableName)
.add("impalaUDF", impalaUDF)
.add("hiveUDF", hiveUDF)
.add("error", error)
.toString();
}
@@ -106,12 +128,13 @@ public boolean equals(Object o) {
Objects.equal(database, that.getDatabase()) &&
Objects.equal(tableName, that.getTableName()) &&
Objects.equal(impalaUDF, that.getImpalaUDF()) &&
Objects.equal(hiveUDF, that.getHiveUDF()) &&
Objects.equal(error, that.getError()));
}

@Override
public int hashCode() {
return Objects.hashCode(database, tableName, impalaUDF, error);
return Objects.hashCode(database, tableName, impalaUDF, hiveUDF, error);
}

}
Original file line number Diff line number Diff line change
@@ -34,10 +34,13 @@ public class ApiHiveReplicationResult {
private List<ApiHiveTable> tables;
private Integer impalaUDFCount;
private List<ApiImpalaUDF> impalaUDFs;
private Integer hiveUDFCount;
private List<ApiHiveUDF> hiveUDFs;
private Integer errorCount;
private List<ApiHiveReplicationError> errors;
private ApiHdfsReplicationResult dataReplicationResult;
private boolean dryRun;
private String runAsUser;

public ApiHiveReplicationResult() {
// For JAX-B
@@ -104,6 +107,19 @@ public void setImpalaUDFCount(Integer impalaUDFCount) {
this.impalaUDFCount = impalaUDFCount;
}

/**
* Number of hive UDFs that were successfully replicated. Available since
* API v14.
*/
@XmlElement
public Integer getHiveUDFCount() {
return hiveUDFCount;
}

public void setHiveUDFCount(Integer hiveUDFCount) {
this.hiveUDFCount = hiveUDFCount;
}

/**
* The list of Impala UDFs successfully replicated. Available since API v6
* in the full view.
@@ -117,6 +133,20 @@ public void setImpalaUDFs(List<ApiImpalaUDF> impalaUDFs) {
this.impalaUDFs = impalaUDFs;
}


/**
* The list of Impala UDFs successfully replicated. Available since API v6
* in the full view.
*/
@XmlElementWrapper
public List<ApiHiveUDF> getHiveUDFs() {
return hiveUDFs;
}

public void setHiveUDFs(List<ApiHiveUDF> hiveUDFs) {
this.hiveUDFs = hiveUDFs;
}

/**
* Number of errors detected during replication job.
* Available since API v4.
@@ -164,20 +194,36 @@ public void setDryRun(boolean dryRun) {
this.dryRun = dryRun;
}

/**
* Name of the of proxy user, if any.
* Available since API v11.
*/
@XmlElement
public String getRunAsUser() {
return runAsUser;
}

public void setRunAsUser(String runAsUser) {
this.runAsUser = runAsUser;
}

@Override
public boolean equals(Object o) {
ApiHiveReplicationResult that = ApiUtils.baseEquals(this, o);
return this == that || (that != null &&
Objects.equal(phase, that.getPhase()) &&
Objects.equal(tables, that.getTables()) &&
Objects.equal(impalaUDFs, that.getImpalaUDFs()) &&
Objects.equal(hiveUDFs, that.getHiveUDFs()) &&
Objects.equal(errors, that.getErrors()) &&
dryRun == that.isDryRun());
dryRun == that.isDryRun() &&
Objects.equal(runAsUser, that.getRunAsUser()));
}

@Override
public int hashCode() {
return Objects.hashCode(phase, tables, impalaUDFs, errors, dryRun);
return Objects.hashCode(phase, tables, impalaUDFs, hiveUDFs, errors, dryRun,
runAsUser);
}

@Override
@@ -186,8 +232,10 @@ public String toString() {
.add("phase", phase)
.add("tables", tables)
.add("impalaUDFs", impalaUDFs)
.add("hiveUDFs", hiveUDFs)
.add("errors", errors)
.add("dryRun", dryRun)
.add("runAsUser", runAsUser)
.toString();
}

Loading