|
23 | 23 | import io.cdap.cdap.api.data.format.StructuredRecord; |
24 | 24 | import io.cdap.cdap.api.data.schema.Schema; |
25 | 25 | import io.cdap.cdap.api.dataset.table.Table; |
| 26 | +import io.cdap.cdap.common.utils.Tasks; |
26 | 27 | import io.cdap.cdap.datapipeline.DataPipelineApp; |
27 | 28 | import io.cdap.cdap.datapipeline.SmartWorkflow; |
28 | 29 | import io.cdap.cdap.etl.api.batch.BatchSink; |
|
58 | 59 | import java.util.ArrayList; |
59 | 60 | import java.util.List; |
60 | 61 | import java.util.Map; |
| 62 | +import java.util.concurrent.ExecutionException; |
61 | 63 | import java.util.concurrent.TimeUnit; |
| 64 | +import java.util.concurrent.TimeoutException; |
62 | 65 | import javax.ws.rs.HttpMethod; |
63 | 66 |
|
64 | 67 | /** |
@@ -174,4 +177,69 @@ private int getFeeds() throws IOException { |
174 | 177 | urlConn.disconnect(); |
175 | 178 | return responseCode; |
176 | 179 | } |
| 180 | + |
| 181 | + @Test |
| 182 | + public void testHTTPSinkMacroUrl() throws Exception { |
| 183 | + String inputDatasetName = "input-http-sink-with-macro"; |
| 184 | + ETLStage source = new ETLStage("source", MockSource.getPlugin(inputDatasetName)); |
| 185 | + Map<String, String> properties = new ImmutableMap.Builder<String, String>() |
| 186 | + .put("url", "${url}") |
| 187 | + .put("method", "PUT") |
| 188 | + .put("messageFormat", "Custom") |
| 189 | + .put("charset", "UTF-8") |
| 190 | + .put("body", "cask cdap, hydrator tracker, ui cli") |
| 191 | + .put("batchSize", "1") |
| 192 | + .put("referenceName", "HTTPSinkReference") |
| 193 | + .put("delimiterForMessages", "\n") |
| 194 | + .put("numRetries", "3") |
| 195 | + .put("followRedirects", "true") |
| 196 | + .put("disableSSLValidation", "true") |
| 197 | + .put("connectTimeout", "60000") |
| 198 | + .put("readTimeout", "60000") |
| 199 | + .put("failOnNon200Response", "true") |
| 200 | + .build(); |
| 201 | + |
| 202 | + ImmutableMap<String, String> runtimeProperties = |
| 203 | + ImmutableMap.of("url", baseURL + "/feeds/users"); |
| 204 | + |
| 205 | + ETLStage sink = new ETLStage("HTTP", new ETLPlugin("HTTP", BatchSink.PLUGIN_TYPE, properties, null)); |
| 206 | + ETLBatchConfig etlConfig = ETLBatchConfig.builder("* * * * *") |
| 207 | + .addStage(source) |
| 208 | + .addStage(sink) |
| 209 | + .addConnection(source.getName(), sink.getName()) |
| 210 | + .build(); |
| 211 | + |
| 212 | + ApplicationManager appManager = deployETL(etlConfig, inputDatasetName); |
| 213 | + |
| 214 | + DataSetManager<Table> inputManager = getDataset(inputDatasetName); |
| 215 | + List<StructuredRecord> input = ImmutableList.of( |
| 216 | + StructuredRecord.builder(inputSchema).set("id", "1").build() |
| 217 | + ); |
| 218 | + MockSource.writeInput(inputManager, input); |
| 219 | + // run the pipeline |
| 220 | + runETLOnce(appManager, runtimeProperties); |
| 221 | + } |
| 222 | + |
| 223 | + /** |
| 224 | + * Run the SmartWorkflow in the given ETL application for once and wait for the workflow's COMPLETED status |
| 225 | + * with 5 minutes timeout. |
| 226 | + * |
| 227 | + * @param appManager the ETL application to run |
| 228 | + * @param arguments the arguments to be passed when running SmartWorkflow |
| 229 | + */ |
| 230 | + protected WorkflowManager runETLOnce(ApplicationManager appManager, Map<String, String> arguments) |
| 231 | + throws TimeoutException, InterruptedException, ExecutionException { |
| 232 | + final WorkflowManager workflowManager = appManager.getWorkflowManager(SmartWorkflow.NAME); |
| 233 | + int numRuns = workflowManager.getHistory().size(); |
| 234 | + workflowManager.start(arguments); |
| 235 | + Tasks.waitFor(numRuns + 1, () -> workflowManager.getHistory().size(), 20, TimeUnit.SECONDS); |
| 236 | + workflowManager.waitForStopped(5, TimeUnit.MINUTES); |
| 237 | + return workflowManager; |
| 238 | + } |
| 239 | + |
| 240 | + protected ApplicationManager deployETL(ETLBatchConfig etlConfig, String appName) throws Exception { |
| 241 | + AppRequest<ETLBatchConfig> appRequest = new AppRequest<>(BATCH_ARTIFACT, etlConfig); |
| 242 | + ApplicationId appId = NamespaceId.DEFAULT.app(appName); |
| 243 | + return deployApplication(appId, appRequest); |
| 244 | + } |
177 | 245 | } |
0 commit comments