| /** |
| * 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.hadoop.gateway; |
| |
| import com.jayway.restassured.RestAssured; |
| import com.jayway.restassured.path.json.JsonPath; |
| import com.jayway.restassured.response.Response; |
| import com.mycila.xmltool.XMLTag; |
| import org.apache.commons.io.FileUtils; |
| import org.apache.commons.io.IOUtils; |
| import org.apache.commons.lang3.ArrayUtils; |
| import org.apache.directory.server.protocol.shared.transport.TcpTransport; |
| import org.apache.hadoop.gateway.config.GatewayConfig; |
| import org.apache.hadoop.gateway.security.ldap.SimpleLdapDirectoryServer; |
| import org.apache.hadoop.gateway.services.DefaultGatewayServices; |
| import org.apache.hadoop.gateway.services.ServiceLifecycleException; |
| import org.apache.hadoop.test.mock.MockServer; |
| import org.apache.http.HttpHost; |
| import org.apache.http.HttpResponse; |
| import org.apache.http.HttpStatus; |
| import org.apache.http.auth.AuthScope; |
| import org.apache.http.auth.UsernamePasswordCredentials; |
| import org.apache.http.client.AuthCache; |
| import org.apache.http.client.methods.HttpGet; |
| import org.apache.http.client.methods.HttpPost; |
| import org.apache.http.client.protocol.ClientContext; |
| import org.apache.http.entity.ContentType; |
| import org.apache.http.entity.StringEntity; |
| import org.apache.http.impl.auth.BasicScheme; |
| import org.apache.http.impl.client.BasicAuthCache; |
| import org.apache.http.impl.client.DefaultHttpClient; |
| import org.apache.http.protocol.BasicHttpContext; |
| import org.apache.http.util.EntityUtils; |
| import org.hamcrest.CoreMatchers; |
| import org.hamcrest.MatcherAssert; |
| import org.hamcrest.Matchers; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.InetAddress; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.net.UnknownHostException; |
| import java.nio.charset.Charset; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.UUID; |
| |
| import static org.junit.Assert.assertThat; |
| import static org.junit.Assert.fail; |
| |
| /** |
| * This class was created to reduce much of the duplication and boiler plate that was ending up in the GatewayBasicFuncTest class. |
| * It basically does a number of different things. |
| * 1) Creates a GATEWAY_HOME starts a gateway instance and deployes a test topology. |
| * 2) Provides a registry of mock Hadoop services. |
| * 3) Provides "bundled" methods for common Hadoop operations to avoid duplication in tests. |
| * 4) Provides methods to access test resources. |
| */ |
| public class GatewayFuncTestDriver { |
| |
| private static Logger log = LoggerFactory.getLogger( GatewayFuncTestDriver.class ); |
| |
| public Class<?> resourceBaseClass; |
| public Map<String,Service> services = new HashMap<String,Service>(); |
| public SimpleLdapDirectoryServer ldap; |
| public TcpTransport ldapTransport; |
| public boolean useGateway; |
| public GatewayServer gateway; |
| public GatewayConfig config; |
| public String clusterName; |
| |
| /** |
| * Sets the class from which relative test resource names should be resolved. |
| * @param resourceBaseClass The class from which relative test resource names should be resolved. |
| */ |
| public void setResourceBase( Class<?> resourceBaseClass ) { |
| this.resourceBaseClass = resourceBaseClass; |
| } |
| |
| /** |
| * Starts an embedded LDAP server of the specified port. |
| * @param port The desired port the LDAP server should listen on. |
| * @return The actual port the LDAP server is listening on. |
| * @throws Exception Thrown if a failure occurs. |
| */ |
| public int setupLdap( int port ) throws Exception { |
| URL usersUrl = getResourceUrl( "users.ldif" ); |
| ldapTransport = new TcpTransport( port ); |
| ldap = new SimpleLdapDirectoryServer( "dc=hadoop,dc=apache,dc=org", new File( usersUrl.toURI() ), ldapTransport ); |
| ldap.start(); |
| log.info( "LDAP port = " + ldapTransport.getAcceptor().getLocalAddress().getPort() ); |
| return port; |
| } |
| |
| /** |
| * Adds a mock service to the registry. |
| */ |
| public void setupService( String role, String realUrl, String gatewayPath, boolean mock ) throws Exception { |
| Service service = new Service( role, realUrl, gatewayPath, mock ); |
| services.put( role, service ); |
| log.info( role + " port = " + service.server.getPort() ); |
| } |
| |
| /** |
| * Creates a GATEWAY_HOME, starts a gateway instance and deploys a test topology. |
| */ |
| public void setupGateway( GatewayTestConfig config, String cluster, XMLTag topology, boolean use ) throws Exception { |
| this.useGateway = use; |
| this.config = config; |
| this.clusterName = cluster; |
| |
| File targetDir = new File( System.getProperty( "user.dir" ), "target" ); |
| File gatewayDir = new File( targetDir, "gateway-home-" + UUID.randomUUID() ); |
| gatewayDir.mkdirs(); |
| |
| config.setGatewayHomeDir( gatewayDir.getAbsolutePath() ); |
| |
| File topoDir = new File( config.getGatewayTopologyDir() ); |
| topoDir.mkdirs(); |
| |
| File deployDir = new File( config.getGatewayDeploymentDir() ); |
| deployDir.mkdirs(); |
| |
| File descriptor = new File( topoDir, cluster + ".xml" ); |
| FileOutputStream stream = new FileOutputStream( descriptor ); |
| topology.toStream( stream ); |
| stream.close(); |
| |
| DefaultGatewayServices srvcs = new DefaultGatewayServices(); |
| Map<String,String> options = new HashMap<String,String>(); |
| options.put("persist-master", "false"); |
| options.put("master", "password"); |
| try { |
| srvcs.init(config, options); |
| } catch (ServiceLifecycleException e) { |
| e.printStackTrace(); // I18N not required. |
| } |
| File stacksDir = new File( config.getGatewayServicesDir() ); |
| stacksDir.mkdirs(); |
| //TODO: [sumit] This is a hack for now, need to find a better way to locate the source resources for 'stacks' to be tested |
| String pathToStacksSource = "gateway-service-definitions/src/main/resources/services"; |
| File stacksSourceDir = new File( targetDir.getParent(), pathToStacksSource); |
| if (!stacksSourceDir.exists()) { |
| stacksSourceDir = new File( targetDir.getParentFile().getParent(), pathToStacksSource); |
| } |
| if (stacksSourceDir.exists()) { |
| FileUtils.copyDirectoryToDirectory(stacksSourceDir, stacksDir); |
| } |
| |
| gateway = GatewayServer.startGateway( config, srvcs ); |
| MatcherAssert.assertThat( "Failed to start gateway.", gateway, CoreMatchers.notNullValue() ); |
| |
| log.info( "Gateway port = " + gateway.getAddresses()[ 0 ].getPort() ); |
| } |
| |
| public void cleanup() throws Exception { |
| gateway.stop(); |
| FileUtils.deleteQuietly( new File( config.getGatewayTopologyDir() ) ); |
| FileUtils.deleteQuietly( new File( config.getGatewayConfDir() ) ); |
| FileUtils.deleteQuietly( new File( config.getGatewaySecurityDir() ) ); |
| FileUtils.deleteQuietly( new File( config.getGatewayDeploymentDir() ) ); |
| FileUtils.deleteQuietly( new File( config.getGatewayDataDir() ) ); |
| FileUtils.deleteQuietly( new File( config.getGatewayServicesDir() ) ); |
| |
| for( Service service : services.values() ) { |
| service.server.stop(); |
| } |
| services.clear(); |
| |
| ldap.stop( true ); |
| } |
| |
| public boolean isUseGateway() { |
| return useGateway; |
| } |
| |
| public MockServer getMock( String serviceRole ) { |
| Service service = services.get( serviceRole ); |
| return service.server; |
| } |
| |
| public String getRealUrl( String serviceRole ) { |
| return getUrl( serviceRole, true ); |
| } |
| |
| public String getUrl( String serviceRole ) { |
| return getUrl( serviceRole, false ); |
| } |
| |
| private String getLocalHostName() { |
| String hostName = "localhost"; |
| try { |
| hostName = InetAddress.getByName( "127.0.0.1" ).getHostName(); |
| } catch( UnknownHostException e ) { |
| // Ignore and use the default. |
| } |
| return hostName; |
| } |
| |
| public String getUrl( String serviceRole, boolean real ) { |
| String url; |
| String localHostName = getLocalHostName(); |
| Service service = services.get( serviceRole ); |
| if( useGateway && !real ) { |
| url = "http://" + localHostName + ":" + gateway.getAddresses()[0].getPort() + "/" + config.getGatewayPath() + service.gatewayPath; |
| } else if( service.mock ) { |
| url = "http://" + localHostName + ":" + service.server.getPort(); |
| } else { |
| url = service.realUrl.toASCIIString(); |
| } |
| return url; |
| } |
| |
| public String getClusterUrl() { |
| String url; |
| String localHostName = getLocalHostName(); |
| url = "http://" + localHostName + ":" + gateway.getAddresses()[0].getPort() + "/" + config.getGatewayPath() + "/" + clusterName; |
| return url; |
| } |
| |
| public int getGatewayPort() { |
| return gateway.getAddresses()[0].getPort(); |
| } |
| |
| public String getRealAddr( String role ) { |
| String addr; |
| String localHostName = getLocalHostName(); |
| Service service = services.get( role ); |
| if( service.mock ) { |
| addr = localHostName + ":" + service.server.getPort(); |
| } else { |
| addr = service.realUrl.getHost() + ":" + service.realUrl.getPort(); |
| } |
| return addr; |
| } |
| |
| public String getLdapUrl() { |
| return "ldap://localhost:" + ldapTransport.getAcceptor().getLocalAddress().getPort(); |
| } |
| |
| private static class Service { |
| String role; |
| URI realUrl; |
| String gatewayPath; |
| boolean mock; |
| MockServer server; |
| private Service( String role, String realUrl, String gatewayPath, boolean mock ) throws Exception { |
| this.role = role; |
| this.realUrl = new URI( realUrl ); |
| this.gatewayPath = gatewayPath; |
| this.mock = mock; |
| this.server = new MockServer( role, true ); |
| } |
| } |
| |
| public String getResourceBaseName() { |
| return resourceBaseClass.getName().replaceAll( "\\.", "/" ) + "/"; |
| } |
| |
| public String getResourceName( String resource ) { |
| return getResourceBaseName() + resource; |
| } |
| |
| public URL getResourceUrl( String resource ) { |
| URL url = ClassLoader.getSystemResource( getResourceName( resource ) ); |
| assertThat( "Failed to find test resource " + resource, url, Matchers.notNullValue() ); |
| return url; |
| } |
| |
| public InputStream getResourceStream( String resource ) throws IOException { |
| InputStream stream = null; |
| if( resource.startsWith( "file:/" ) ) { |
| try { |
| stream = FileUtils.openInputStream( new File( new URI( resource ) ) ); |
| } catch( URISyntaxException e ) { |
| throw new IOException( e ); |
| } |
| } else { |
| stream = ClassLoader.getSystemResourceAsStream( getResourceName( resource ) ); |
| } |
| assertThat( "Failed to find test resource " + resource, stream, Matchers.notNullValue() ); |
| return stream; |
| } |
| |
| public byte[] getResourceBytes( String resource ) throws IOException { |
| return IOUtils.toByteArray( getResourceStream( resource ) ); |
| } |
| |
| public String getResourceString( String resource, Charset charset ) throws IOException { |
| return IOUtils.toString( getResourceBytes( resource ), "UTF-8" ); |
| } |
| |
| public void assertComplete() { |
| // Check to make sure that all interaction were satisfied if for mocked services. |
| // Otherwise just clear the mock interaction queue. |
| for( Service service : services.values() ) { |
| if( service.mock ) { |
| assertThat( |
| "Service " + service.role + " has remaining expected interactions.", |
| service.server.getCount(), Matchers.is(0) ); |
| } |
| service.server.reset(); |
| } |
| } |
| |
| |
| public void assertNotComplete(String serviceName) { |
| // Check to make sure that all interaction were satisfied if for mocked services. |
| // Otherwise just clear the mock interaction queue. |
| |
| Service service = services.get(serviceName); |
| |
| if(service != null) { |
| if(service.mock) { |
| assertThat( |
| "Service " + service.role + " has remaining expected interactions.", |
| service.server.getCount(), Matchers.not(0)); |
| } |
| service.server.reset(); |
| } else { |
| fail(); |
| } |
| } |
| |
| public void reset() { |
| for( Service service : services.values() ) { |
| service.server.reset(); |
| } |
| } |
| |
| public String createFileNN( String user, String password, String file, String permsOctal, int status ) throws IOException { |
| if( status == HttpStatus.SC_TEMPORARY_REDIRECT ) { |
| getMock( "WEBHDFS" ) |
| .expect() |
| .method( "PUT" ) |
| .pathInfo( "/v1" + file ) |
| .queryParam( "user.name", user ) |
| .queryParam( "op", "CREATE" ) |
| .respond() |
| .status( status ) |
| .header( "Location", getRealUrl("DATANODE") + file + "?op=CREATE&user.name="+user ); |
| } else { |
| getMock( "WEBHDFS" ) |
| .expect() |
| .method( "PUT" ) |
| .pathInfo( "/v1" + file ) |
| .queryParam( "user.name", user ) |
| .queryParam( "op", "CREATE" ) |
| .respond() |
| .status( status ); |
| } |
| Response response = RestAssured.given() |
| //.log().headers() |
| //.log().parameters() |
| .auth().preemptive().basic( user, password ) |
| .header( "X-XSRF-Header", "jksdhfkhdsf" ) |
| .queryParam( "op", "CREATE" ) |
| .queryParam( "permission", permsOctal ) |
| .expect() |
| //.log().all() |
| .statusCode( status ) |
| .when().put( getUrl( "WEBHDFS" ) + "/v1" + file + ( isUseGateway() ? "" : "?user.name=" + user ) ); |
| String location = response.getHeader( "Location" ); |
| log.trace( "Redirect location: " + response.getHeader( "Location" ) ); |
| return location; |
| } |
| |
| public int createFileDN( String user, String password, String path, String location, String contentType, String resource, int status ) throws IOException { |
| if( status == HttpStatus.SC_CREATED ) { |
| getMock( "DATANODE" ) |
| .expect() |
| .method( "PUT" ) |
| .pathInfo( path ) |
| .queryParam( "user.name", user ) |
| .queryParam( "op", "CREATE" ) |
| .contentType( contentType ) |
| .content( getResourceBytes( resource ) ) |
| .respond() |
| .status( status ) |
| .header( "Location", "webhdfs://" + getRealAddr( "DATANODE" ) + "/v1" + path ); |
| } else { |
| getMock( "DATANODE" ) |
| .expect() |
| .method( "PUT" ) |
| .pathInfo( path ) |
| .queryParam( "user.name", user ) |
| .queryParam( "op", "CREATE" ) |
| .contentType( contentType ) |
| .content( getResourceStream( resource ) ) |
| .respond() |
| .status( status ); |
| } |
| Response response = RestAssured.given() |
| //.log().all() |
| .auth().preemptive().basic( user, password ) |
| .header( "X-XSRF-Header", "jksdhfkhdsf" ) |
| .contentType( contentType ) |
| .content( getResourceBytes( resource ) ) |
| .expect() |
| //.log().all() |
| .statusCode( status ) |
| .when().put( location ); |
| return response.getStatusCode(); |
| } |
| |
| public String createFile( |
| String user, String password, String group, String file, String permsOctal, String contentType, String resource, |
| int nnStatus, int dnStatus, int chownStatus ) throws IOException { |
| String location = createFileNN( user, password, file, permsOctal, nnStatus ); |
| if( location != null ) { |
| int status = createFileDN( user, password, file, location, contentType, resource, dnStatus ); |
| if( status < 300 && permsOctal != null ) { |
| chmodFile( user, password, file, permsOctal, chownStatus ); |
| if( group != null ) { |
| chownFile( user, password, file, user, group, chownStatus ); |
| } |
| } |
| } |
| assertComplete(); |
| return location; |
| } |
| |
| public void readFile( String user, String password, String file, String contentType, String resource, int status ) throws IOException { |
| getMock( "WEBHDFS" ) |
| .expect() |
| .method( "GET" ) |
| .pathInfo( "/v1" + file ) |
| .queryParam( "user.name", user ) |
| .queryParam( "op", "OPEN" ) |
| .respond() |
| .status( HttpStatus.SC_TEMPORARY_REDIRECT ) |
| .header( "Location", getRealUrl( "DATANODE" ) + file + "?op=OPEN&user.name="+user ); |
| if( status == HttpStatus.SC_OK ) { |
| getMock( "DATANODE" ) |
| .expect() |
| .method( "GET" ) |
| .pathInfo( file ) |
| .queryParam( "user.name", user ) |
| .queryParam( "op", "OPEN" ) |
| .respond() |
| .status( status ) |
| .contentType( contentType ) |
| .content( getResourceBytes( resource ) ); |
| } else { |
| getMock( "DATANODE" ) |
| .expect() |
| .method( "GET" ) |
| .pathInfo( file ) |
| .queryParam( "user.name", user ) |
| .queryParam( "op", "OPEN" ) |
| .respond() |
| .status( status ); |
| } |
| Response response = RestAssured.given() |
| //.log().all() |
| .auth().preemptive().basic( user, password ) |
| .header( "X-XSRF-Header", "jksdhfkhdsf" ) |
| .queryParam( "op", "OPEN" ) |
| .expect() |
| //.log().all() |
| .statusCode( status ) |
| .when().get( getUrl("WEBHDFS") + "/v1" + file + ( isUseGateway() ? "" : "?user.name=" + user ) ); |
| if( response.getStatusCode() == HttpStatus.SC_OK ) { |
| String actualContent = response.asString(); |
| String expectedContent = getResourceString( resource, Charset.forName("UTF-8") ); |
| assertThat( actualContent, Matchers.is(expectedContent) ); |
| } |
| assertComplete(); |
| } |
| |
| public void chownFile( String user, String password, String file, String owner, String group, int status ) { |
| getMock( "WEBHDFS" ) |
| .expect() |
| .method( "PUT" ) |
| .pathInfo( "/v1" + file ) |
| .queryParam( "op", "SETOWNER" ) |
| .queryParam( "user.name", user ) |
| .queryParam( "owner", owner ) |
| .queryParam( "group", group ) |
| .respond() |
| .status( HttpStatus.SC_OK ); |
| RestAssured.given() |
| //.log().all() |
| .auth().preemptive().basic( user, password ) |
| .header( "X-XSRF-Header", "jksdhfkhdsf" ) |
| .queryParam( "op", "SETOWNER" ) |
| .queryParam( "owner", owner ) |
| .queryParam( "group", group ) |
| .expect() |
| //.log().all() |
| .statusCode( status ) |
| .when().put( getUrl("WEBHDFS") + "/v1" + file + ( isUseGateway() ? "" : "?user.name=" + user ) ); |
| assertComplete(); |
| } |
| |
| public void chmodFile( String user, String password, String file, String permsOctal, int status ) { |
| getMock( "WEBHDFS" ) |
| .expect() |
| .method( "PUT" ) |
| .pathInfo( "/v1" + file ) |
| .queryParam( "op", "SETPERMISSION" ) |
| .queryParam( "user.name", user ) |
| .queryParam( "permission", permsOctal ) |
| .respond() |
| .status( HttpStatus.SC_OK ); |
| RestAssured.given() |
| //.log().all() |
| .auth().preemptive().basic( user, password ) |
| .header( "X-XSRF-Header", "jksdhfkhdsf" ) |
| .queryParam( "op", "SETPERMISSION" ) |
| .queryParam( "permission", permsOctal ) |
| .expect() |
| //.log().all() |
| .statusCode( status ) |
| .when().put( getUrl("WEBHDFS") + "/v1" + file + ( isUseGateway() ? "" : "?user.name=" + user ) ); |
| assertComplete(); |
| } |
| |
| public String updateFile( String user, String password, String file, String contentType, String resource, int nnStatus, int dnStatus ) throws IOException { |
| String location; |
| location = updateFileNN( user, password, file, resource, nnStatus ); |
| if( location != null ) { |
| updateFileDN( user, password, file, location, contentType, resource, dnStatus ); |
| } |
| assertComplete(); |
| return location; |
| } |
| |
| public String updateFileNN( String user, String password, String file, String resource, int status ) throws IOException { |
| if( status == HttpStatus.SC_TEMPORARY_REDIRECT ) { |
| getMock( "WEBHDFS" ) |
| .expect() |
| .method( "PUT" ) |
| .pathInfo( "/v1" + file ) |
| .queryParam( "op", "CREATE" ) |
| .queryParam( "user.name", user ) |
| .queryParam( "overwrite", "true" ) |
| .respond() |
| .status( status ) |
| .header( "Location", getRealUrl("DATANODE") + file + "?op=CREATE&user.name="+user ); |
| } else { |
| getMock( "WEBHDFS" ) |
| .expect() |
| .method( "PUT" ) |
| .pathInfo( "v1" + file ) |
| .queryParam( "user.name", user ) |
| .queryParam( "op", "CREATE" ) |
| .respond() |
| .status( status ); |
| } |
| Response response = RestAssured.given() |
| //.log().all() |
| .auth().preemptive().basic( user, password ) |
| .header( "X-XSRF-Header", "jksdhfkhdsf" ) |
| .queryParam( "op", "CREATE" ) |
| .queryParam( "overwrite", "true" ) |
| .content( getResourceBytes( resource ) ) |
| .expect() |
| //.log().all() |
| .statusCode( status ) |
| .when().put( getUrl("WEBHDFS") + "/v1" + file + ( isUseGateway() ? "" : "?user.name=" + user ) ); |
| String location = response.getHeader( "Location" ); |
| log.trace( "Redirect location: " + response.getHeader( "Location" ) ); |
| return location; |
| } |
| |
| public void updateFileDN( String user, String password, String path, String location, String contentType, String resource, int status ) throws IOException { |
| if( status == HttpStatus.SC_CREATED ) { |
| getMock( "DATANODE" ) |
| .expect() |
| .method( "PUT" ) |
| .pathInfo( path ) |
| .queryParam( "user.name", user ) |
| .queryParam( "op", "CREATE" ) |
| .contentType( contentType ) |
| .content( getResourceBytes( resource ) ) |
| .respond() |
| .status( status ) |
| .header( "Location", "webhdfs://" + getRealAddr( "DATANODE" ) + "/v1" + path ); |
| } else { |
| getMock( "DATANODE" ) |
| .expect() |
| .method( "PUT" ) |
| .pathInfo( path ) |
| .queryParam( "user.name", user ) |
| .queryParam( "op", "CREATE" ) |
| .contentType( contentType ) |
| .content( getResourceBytes( resource ) ) |
| .respond() |
| .status( status ); |
| } |
| Response response = RestAssured.given() |
| //.log().all() |
| .auth().preemptive().basic( user, password ) |
| .header( "X-XSRF-Header", "jksdhfkhdsf" ) |
| .queryParam( "op", "CREATE" ) |
| .queryParam( "overwrite", "true" ) |
| .contentType( contentType ) |
| .content( getResourceBytes( resource ) ) |
| .expect() |
| //.log().all() |
| .statusCode( status ) |
| .when().put( location ); |
| } |
| |
| public void deleteFile( String user, String password, String file, String recursive, int... status ) { |
| getMock( "WEBHDFS" ) |
| .expect() |
| .method( "DELETE" ) |
| .pathInfo( "/v1" + file ) |
| .queryParam( "user.name", user ) |
| .queryParam( "op", "DELETE" ) |
| .queryParam( "recursive", recursive ) |
| .respond().status( status[0] ); |
| RestAssured.given() |
| //.log().all() |
| .auth().preemptive().basic( user, password ) |
| .header( "X-XSRF-Header", "jksdhfkhdsf" ) |
| .queryParam( "op", "DELETE" ) |
| .queryParam( "recursive", recursive ) |
| .expect() |
| //.log().all() |
| .statusCode( Matchers.isIn(ArrayUtils.toObject(status)) ) |
| .when() |
| .delete( getUrl( "WEBHDFS" ) + "/v1" + file + ( isUseGateway() ? "" : "?user.name=" + user ) ); |
| assertComplete(); |
| } |
| |
| public String createDir( String user, String password, String dir, String permsOctal, int status ) { |
| getMock( "WEBHDFS" ) |
| .expect() |
| .method( "PUT" ) |
| .pathInfo( "/v1" + dir ) |
| .queryParam( "op", "MKDIRS" ) |
| .queryParam( "user.name", user ) |
| .queryParam( "permission", permsOctal ) |
| .respond() |
| .status( HttpStatus.SC_OK ) |
| .contentType( "application/json" ) |
| .content( "{\"boolean\": true}".getBytes() ); |
| Response response = RestAssured.given() |
| //.log().all() |
| .auth().preemptive().basic( user, password ) |
| .header( "X-XSRF-Header", "jksdhfkhdsf" ) |
| .queryParam( "op", "MKDIRS" ) |
| .queryParam( "permission", permsOctal ) |
| .expect() |
| //.log().all() |
| .statusCode( status ) |
| .contentType( "application/json" ) |
| .content( "boolean", CoreMatchers.equalTo(true) ) |
| .when() |
| .put( getUrl("WEBHDFS") + "/v1" + dir + ( isUseGateway() ? "" : "?user.name=" + user ) ); |
| String location = response.getHeader( "Location" ); |
| return location; |
| } |
| |
| public String createDir( String user, String password, String group, String dir, String permsOctal, int nnStatus, int chownStatus ) { |
| String location = createDir( user, password, dir, permsOctal, nnStatus ); |
| if( location != null ) { |
| chownFile( user, password, dir, user, group, chownStatus ); |
| } |
| return location; |
| } |
| |
| public void readDir( String user, String password, String dir, String resource, int status ) { |
| RestAssured.given() |
| //.log().all() |
| .auth().preemptive().basic( user, password ) |
| .queryParam( "op", "LISTSTATUS" ) |
| .expect() |
| //.log().all() |
| .statusCode( status ) |
| .content( CoreMatchers.equalTo("TODO") ) |
| .when() |
| .get( getUrl( "WEBHDFS" ) + "/v1" + dir ); |
| } |
| |
| public String submitJava( String user, String password, String jar, String main, String input, String output, int status ) { |
| getMock( "WEBHCAT" ) |
| .expect() |
| .method( "POST" ) |
| .pathInfo( "/v1/mapreduce/jar" ) |
| .formParam( "user.name", user ) |
| .formParam( "jar", jar ) |
| .formParam( "class", main ) |
| .formParam( "arg", input, output ) |
| .respond() |
| .status( status ) |
| .contentType( "application/json" ) |
| .content( "{\"id\":\"job_201210301335_0086\"}".getBytes() ); |
| String json = RestAssured.given() |
| //.log().all() |
| .auth().preemptive().basic( user, password ) |
| .header( "X-XSRF-Header", "jksdhfkhdsf" ) |
| .formParam( "user.name", user ) |
| .formParam( "jar", jar ) //"/user/hdfs/test/hadoop-examples.jar" ) |
| .formParam( "class", main ) //"org.apache.org.apache.hadoop.examples.WordCount" ) |
| .formParam( "arg", input, output ) //.formParam( "arg", "/user/hdfs/test/input", "/user/hdfs/test/output" ) |
| .expect() |
| //.log().all() |
| .statusCode( status ) |
| .when().post( getUrl( "WEBHCAT" ) + "/v1/mapreduce/jar" + ( isUseGateway() ? "" : "?user.name=" + user ) ).asString(); |
| log.trace( "JSON=" + json ); |
| String job = JsonPath.from(json).getString( "id" ); |
| log.debug( "JOB=" + job ); |
| assertComplete(); |
| return job; |
| } |
| |
| public String submitPig( String user, String password, String group, String file, String arg, String statusDir, int... status ) { |
| getMock( "WEBHCAT" ) |
| .expect() |
| .method( "POST" ) |
| .pathInfo( "/v1/pig" ) |
| .respond() |
| .status( status[0] ) |
| .contentType( "application/json" ) |
| .content( "{\"id\":\"job_201210301335_0086\"}".getBytes() ); |
| String json = RestAssured.given() |
| //.log().all() |
| .auth().preemptive().basic( user, password ) |
| .header( "X-XSRF-Header", "jksdhfkhdsf" ) |
| //BUG: The identity asserter needs to check for this too. |
| .formParam( "user.name", user ) |
| .formParam( "group", group ) |
| .formParam( "file", file ) |
| .formParam( "arg", arg ) |
| .formParam( "statusdir", statusDir ) |
| .expect() |
| //.log().all(); |
| .statusCode( Matchers.isIn(ArrayUtils.toObject(status)) ) |
| .contentType( "application/json" ) |
| //.content( "boolean", equalTo( true ) ) |
| .when() |
| .post( getUrl( "WEBHCAT" ) + "/v1/pig" + ( isUseGateway() ? "" : "?user.name=" + user ) ) |
| .asString(); |
| log.trace( "JSON=" + json ); |
| String job = JsonPath.from(json).getString( "id" ); |
| log.debug( "JOB=" + job ); |
| assertComplete(); |
| return job; |
| } |
| |
| public String submitHive( String user, String password, String group, String file, String statusDir, int... status ) { |
| getMock( "WEBHCAT" ) |
| .expect() |
| .method( "POST" ) |
| .pathInfo( "/v1/hive" ) |
| .respond() |
| .status( status[ 0 ] ) |
| .contentType( "application/json" ) |
| .content( "{\"id\":\"job_201210301335_0086\"}".getBytes() ); |
| String json = RestAssured.given() |
| //.log().all() |
| .auth().preemptive().basic( user, password ) |
| .header( "X-XSRF-Header", "jksdhfkhdsf" ) |
| .formParam( "user.name", user ) |
| .formParam( "group", group ) |
| .formParam( "group", group ) |
| .formParam( "file", file ) |
| .formParam( "statusdir", statusDir ) |
| .expect() |
| //.log().all() |
| .statusCode( Matchers.isIn(ArrayUtils.toObject(status)) ) |
| .contentType( "application/json" ) |
| //.content( "boolean", equalTo( true ) ) |
| .when() |
| .post( getUrl( "WEBHCAT" ) + "/v1/hive" + ( isUseGateway() ? "" : "?user.name=" + user ) ) |
| .asString(); |
| log.trace( "JSON=" + json ); |
| String job = JsonPath.from(json).getString( "id" ); |
| log.debug( "JOB=" + job ); |
| assertComplete(); |
| return job; |
| } |
| |
| public void queryQueue( String user, String password, String job ) throws IOException { |
| getMock( "WEBHCAT" ) |
| .expect() |
| .method( "GET" ) |
| .pathInfo( "/v1/jobs/" + job ) |
| .respond() |
| .status( HttpStatus.SC_OK ) |
| .content( getResourceBytes( "webhcat-job-status.json" ) ) |
| .contentType( "application/json" ); |
| String status = RestAssured.given() |
| //.log().all() |
| .auth().preemptive().basic( user, password ) |
| .header( "X-XSRF-Header", "jksdhfkhdsf" ) |
| .pathParam( "job", job ) |
| .expect() |
| //.log().all() |
| .content( "status.jobId", CoreMatchers.equalTo(job) ) |
| .statusCode( HttpStatus.SC_OK ) |
| .when().get( getUrl( "WEBHCAT" ) + "/v1/jobs/{job}" + ( isUseGateway() ? "" : "?user.name=" + user ) ).asString(); |
| log.debug( "STATUS=" + status ); |
| assertComplete(); |
| } |
| |
| /* GET /oozie/versions |
| HTTP/1.1 200 OK |
| Content-Type: application/json;charset=UTF-8 |
| Content-Length: 5 |
| Server: Apache-Coyote/1.1 |
| Date: Thu, 14 Feb 2013 15:47:51 GMT |
| See: oozie-versions.json |
| */ |
| public void oozieGetVersions( String user, String password ) throws IOException { |
| RestAssured.given() |
| .auth().preemptive().basic( user, password ) |
| .header( "X-XSRF-Header", "jksdhfkhdsf" ) |
| .expect() |
| .statusCode( 200 ) |
| .body( "", Matchers.hasItems(0, 1) ) |
| .when().get( getUrl( "OOZIE" ) + "/versions" + ( isUseGateway() ? "" : "?user.name=" + user ) ).asString(); |
| } |
| |
| /* GET /oozie/v1/admin/status |
| HTTP/1.1 200 OK |
| Content-Type: application/json;charset=UTF-8 |
| Content-Length: 23 |
| Server: Apache-Coyote/1.1 |
| Date: Thu, 14 Feb 2013 15:49:16 GMT |
| See: oozie-admin-status.json |
| */ |
| |
| /* PUT /oozie/v1/admin/status?safemode=true |
| TODO |
| */ |
| |
| /* GET /oozie/v1/admin/os-env |
| HTTP/1.1 200 OK |
| Content-Type: application/json;charset=UTF-8 |
| Content-Length: 2039 |
| Server: Apache-Coyote/1.1 |
| Date: Thu, 14 Feb 2013 15:51:56 GMT |
| See: oozie-admin-os-env.json |
| */ |
| |
| /* GET /oozie/v1/admin/java-sys-properties |
| HTTP/1.1 200 OK |
| Content-Type: application/json;charset=UTF-8 |
| Content-Length: 3673 |
| Server: Apache-Coyote/1.1 |
| Date: Thu, 14 Feb 2013 15:53:00 GMT |
| See: oozie-admin-java-sys-properties.json |
| */ |
| |
| /* GET /oozie/v1/admin/configuration |
| HTTP/1.1 200 OK |
| Transfer-Encoding: Identity |
| Content-Type: application/json;charset=UTF-8 |
| Server: Apache-Coyote/1.1 |
| Date: Thu, 14 Feb 2013 15:53:31 GMT |
| See: oozie-admin-configuration.json |
| */ |
| |
| /* GET /oozie/v1/admin/instrumentation |
| HTTP/1.1 200 OK |
| Transfer-Encoding: Identity |
| Content-Type: application/json;charset=UTF-8 |
| Server: Apache-Coyote/1.1 |
| Date: Thu, 14 Feb 2013 15:55:43 GMT |
| See: oozie-admin-instrumentation.json |
| */ |
| |
| /* GET /oozie/v1/admin/build-version |
| HTTP/1.1 200 OK |
| Content-Type: application/json;charset=UTF-8 |
| Content-Length: 27 |
| Server: Apache-Coyote/1.1 |
| Date: Thu, 14 Feb 2013 16:08:31 GMT |
| See: oozie-admin-build-version.json |
| */ |
| |
| /* POST /oozie/v1/jobs (request XML; contains URL, response JSON) |
| Content-Type: application/json;charset=UTF-8 |
| Content-Length: 45 |
| Server: Apache-Coyote/1.1 |
| Date: Thu, 14 Feb 2013 18:10:52 GMT |
| */ |
| public String oozieSubmitJob( String user, String password, String request, int status ) throws IOException, URISyntaxException { |
| getMock( "OOZIE" ) |
| .expect() |
| .method( "POST" ) |
| .pathInfo( "/v1/jobs" ) |
| .respond() |
| .status( HttpStatus.SC_CREATED ) |
| .content( getResourceBytes( "oozie-jobs-submit-response.json" ) ) |
| .contentType( "application/json" ); |
| //System.out.println( "REQUEST LENGTH = " + request.length() ); |
| |
| URL url = new URL( getUrl( "OOZIE" ) + "/v1/jobs?action=start" + ( isUseGateway() ? "" : "&user.name=" + user ) ); |
| HttpHost targetHost = new HttpHost( url.getHost(), url.getPort(), url.getProtocol() ); |
| DefaultHttpClient client = new DefaultHttpClient(); |
| client.getCredentialsProvider().setCredentials( |
| new AuthScope( targetHost ), |
| new UsernamePasswordCredentials( user, password ) ); |
| |
| // Create AuthCache instance |
| AuthCache authCache = new BasicAuthCache(); |
| // Generate BASIC scheme object and add it to the local auth cache |
| BasicScheme basicAuth = new BasicScheme(); |
| authCache.put( targetHost, basicAuth ); |
| // Add AuthCache to the execution context |
| BasicHttpContext localContext = new BasicHttpContext(); |
| localContext.setAttribute( ClientContext.AUTH_CACHE, authCache ); |
| |
| HttpPost post = new HttpPost( url.toURI() ); |
| // post.getParams().setParameter( "action", "start" ); |
| StringEntity entity = new StringEntity( request, ContentType.create( "application/xml", "UTF-8" ) ); |
| post.setEntity( entity ); |
| post.setHeader( "X-XSRF-Header", "ksdjfhdsjkfhds" ); |
| HttpResponse response = client.execute( targetHost, post, localContext ); |
| assertThat( response.getStatusLine().getStatusCode(), Matchers.is(status) ); |
| String json = EntityUtils.toString( response.getEntity() ); |
| |
| // String json = given() |
| // .log().all() |
| // .auth().preemptive().basic( user, password ) |
| // .queryParam( "action", "start" ) |
| // .contentType( "application/xml;charset=UTF-8" ) |
| // .content( request ) |
| // .expect() |
| // .log().all() |
| // .statusCode( status ) |
| // .when().post( getUrl( "OOZIE" ) + "/v1/jobs" + ( isUseGateway() ? "" : "?user.name=" + user ) ).asString(); |
| //System.out.println( "JSON=" + json ); |
| String id = JsonPath.from(json).getString( "id" ); |
| return id; |
| } |
| |
| /* GET /oozie/v1/jobs?filter=user%3Dbansalm&offset=1&len=50 (body JSON; contains URL) |
| HTTP/1.1 200 OK |
| Content-Type: application/json;charset=UTF-8 |
| Content-Length: 46 |
| Server: Apache-Coyote/1.1 |
| Date: Thu, 14 Feb 2013 16:10:25 GMT |
| */ |
| |
| /* GET /oozie/v1/job/0000000-130214094519989-oozie-oozi-W |
| HTTP/1.1 200 OK |
| Content-Type: application/json;charset=UTF-8 |
| Content-Length: 2611 |
| Server: Apache-Coyote/1.1 |
| Date: Thu, 14 Feb 2013 17:39:36 GMT |
| */ |
| |
| /* http://192.168.56.101:11000/oozie/v1/job/0000000-130214094519989-oozie-oozi-W?action=start&user.name=sandbox |
| HTTP/1.1 200 OK |
| Date: Thu, 14 Feb 2013 17:52:13 GMT |
| Content-Length: 0 |
| Server: Apache-Coyote/1.1 |
| Set-Cookie: hadoop.auth="u=sandbox&p=sandbox&t=simple&e=1360900333149&s=AU/GeHDNBuK9RBRaBJfrqatjfz8="; Version=1; Path=/ |
| */ |
| |
| /* PUT /oozie/v1/job/job-3?action=rerun (request body XML, contains URL) |
| HTTP/1.1 200 OK |
| Date: Thu, 14 Feb 2013 18:07:45 GMT |
| Content-Length: 0 |
| Server: Apache-Coyote/1.1 |
| Set-Cookie: hadoop.auth="u=sandbox&p=sandbox&t=simple&e=1360901264892&s=DCOczPqn9mcisCeOb5x2C7LIRc8="; Version=1; Path=/ |
| */ |
| |
| /* GET /oozie/v1/job/0000000-130214094519989-oozie-oozi-W?show=info (body JSON, contains URL) |
| HTTP/1.1 200 OK |
| Content-Type: application/json;charset=UTF-8 |
| Content-Length: 2611 |
| Server: Apache-Coyote/1.1 |
| Date: Thu, 14 Feb 2013 17:45:23 GMT |
| */ |
| public String oozieQueryJobStatus( String user, String password, String id, int status ) throws Exception { |
| getMock( "OOZIE" ) |
| .expect() |
| .method( "GET" ) |
| .pathInfo( "/v1/job/" + id ) |
| .respond() |
| .status( HttpStatus.SC_OK ) |
| .content( getResourceBytes( "oozie-job-show-info.json" ) ) |
| .contentType( "application/json" ); |
| |
| //NOTE: For some reason REST-assured doesn't like this and ends up failing with Content-Length issues. |
| URL url = new URL( getUrl( "OOZIE" ) + "/v1/job/" + id + ( isUseGateway() ? "" : "?user.name=" + user ) ); |
| HttpHost targetHost = new HttpHost( url.getHost(), url.getPort(), url.getProtocol() ); |
| DefaultHttpClient client = new DefaultHttpClient(); |
| client.getCredentialsProvider().setCredentials( |
| new AuthScope( targetHost ), |
| new UsernamePasswordCredentials( user, password ) ); |
| |
| // Create AuthCache instance |
| AuthCache authCache = new BasicAuthCache(); |
| // Generate BASIC scheme object and add it to the local auth cache |
| BasicScheme basicAuth = new BasicScheme(); |
| authCache.put( targetHost, basicAuth ); |
| // Add AuthCache to the execution context |
| BasicHttpContext localContext = new BasicHttpContext(); |
| localContext.setAttribute( ClientContext.AUTH_CACHE, authCache ); |
| |
| HttpGet request = new HttpGet( url.toURI() ); |
| request.setHeader("X-XSRF-Header", "ksdhfjkhdsjkf"); |
| HttpResponse response = client.execute( targetHost, request, localContext ); |
| assertThat( response.getStatusLine().getStatusCode(), Matchers.is(status) ); |
| String json = EntityUtils.toString( response.getEntity() ); |
| String jobStatus = JsonPath.from(json).getString( "status" ); |
| return jobStatus; |
| } |
| |
| /* GET /oozie/v1/job/0000000-130214094519989-oozie-oozi-W?show=definition |
| HTTP/1.1 200 OK |
| Content-Type: application/xml;charset=UTF-8 |
| Content-Length: 1494 |
| Server: Apache-Coyote/1.1 |
| Date: Thu, 14 Feb 2013 17:43:30 GMT |
| */ |
| |
| /* GET GET /oozie/v1/job/0000000-130214094519989-oozie-oozi-W?show=log |
| HTTP/1.1 200 OK |
| Transfer-Encoding: Identity |
| Content-Type: text/plain;charset=UTF-8 |
| Server: Apache-Coyote/1.1 |
| Date: Thu, 14 Feb 2013 17:41:43 GMT |
| */ |
| |
| } |