/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ambari.view.utils.ambari;
import org.apache.ambari.view.AmbariHttpException;
import org.apache.ambari.view.URLStreamProvider;
import org.apache.ambari.view.ViewContext;
import org.apache.ambari.view.cluster.Cluster;
import org.apache.commons.io.IOUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Provides API to Ambari. Supports both Local and Remote cluster association.
* Also provides API to get cluster topology (determine what node contains specific service)
* on both local and remote cluster.
*/
public class AmbariApi {
private ViewContext context;
private Services services;
private String requestedBy = "views";
public static String API_PREFIX = "/api/v1/clusters/";
/**
* Constructor for Ambari API based on ViewContext
* @param context View Context
*/
public AmbariApi(ViewContext context) {
this.context = context;
}
/**
* Set requestedBy header
*
* @param requestedBy
*/
public void setRequestedBy(String requestedBy) {
this.requestedBy = requestedBy;
}
/**
* Shortcut for GET method
* @param path REST API path
* @return response
* @throws AmbariApiException
*/
public String requestClusterAPI(String path) throws AmbariApiException, AmbariHttpException {
return requestClusterAPI(path, "GET", null, null);
}
/**
* Request to Ambari REST API for current cluster. Supports both local and remote cluster
* @param path REST API path after cluster name e.g. /api/v1/clusters/mycluster/[method]
* @param method HTTP method
* @param data HTTP data
* @param headers HTTP headers
* @return response
* @throws AmbariApiException IO error or not associated with cluster
*/
public String requestClusterAPI(String path, String method, String data, Map<String, String> headers) throws AmbariApiException, AmbariHttpException {
String response;
try {
if (context.getAmbariClusterStreamProvider() == null || context.getCluster() == null) {
throw new NoClusterAssociatedException(
"RA030 View is not associated with any cluster. No way to request Ambari.");
}
if(!path.startsWith("/")) path = "/" + path;
path = API_PREFIX + context.getCluster().getName() + path;
InputStream inputStream = context.getAmbariClusterStreamProvider().readFrom(path, method, data, addRequestedByHeader(headers));
response = IOUtils.toString(inputStream);
} catch (IOException e) {
throw new AmbariApiException("RA040 I/O error while requesting Ambari", e);
}
return response;
}
/**
* Request to Ambari REST API. Supports both local and remote cluster
* @param path REST API path, e.g. /api/v1/clusters/mycluster/
* @param method HTTP method
* @param data HTTP data
* @param headers HTTP headers
* @return response
* @throws AmbariApiException IO error or not associated with cluster
*/
public String readFromAmbari(String path, String method, String data, Map<String, String> headers) throws AmbariApiException, AmbariHttpException {
String response;
try {
if (context.getAmbariClusterStreamProvider() == null) {
throw new NoClusterAssociatedException(
"RA060 View is not associated with any cluster. No way to request Ambari.");
}
InputStream inputStream = context.getAmbariClusterStreamProvider().readFrom(path, method, data, addRequestedByHeader(headers));
response = IOUtils.toString(inputStream);
} catch (IOException e) {
throw new AmbariApiException("RA050 I/O error while requesting Ambari", e);
}
return response;
}
/**
* Provides access to service-specific utilities
* @return object with service-specific methods
*/
public Services getServices() {
if (services == null) {
services = new Services(this, context);
}
return services;
}
private Map<String,String> addRequestedByHeader(Map<String,String> headers){
if(headers == null){
headers = new HashMap<String, String>();
}
headers.put("X-Requested-By",this.requestedBy);
return headers;
}
/**
* Check if view is associated with cluster
*
* @return isClusterAssociated
*/
public boolean isClusterAssociated(){
return context.getCluster() != null;
}
}