You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2021/03/19 06:39:47 UTC

[camel] 12/22: CAMEL-15963 Create a Google Cloud Functions component

This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit e8896b4419222445329e061e3e7e1775acabf8c1
Author: Raffaele Marcello <ma...@gmail.com>
AuthorDate: Thu Mar 11 14:52:22 2021 +0100

    CAMEL-15963 Create a Google Cloud Functions component
---
 .../functions/GoogleCloudFunctionsConstants.java   |  36 +-----
 .../functions/GoogleCloudFunctionsProducer.java    |  90 +++++++++-----
 .../integration/ComplexIntegrationTest.java        | 138 ---------------------
 .../functions/integration/IntegrationTest.java     | 127 +++++++++++++++++++
 .../unit/GoogleCloudFunctionsComponentTest.java    |  44 +++++--
 .../src/test/resources/log4j.properties            |   2 +-
 6 files changed, 222 insertions(+), 215 deletions(-)

diff --git a/components/camel-google-functions/src/main/java/org/apache/camel/component/google/functions/GoogleCloudFunctionsConstants.java b/components/camel-google-functions/src/main/java/org/apache/camel/component/google/functions/GoogleCloudFunctionsConstants.java
index b90f6d1..b56df85 100644
--- a/components/camel-google-functions/src/main/java/org/apache/camel/component/google/functions/GoogleCloudFunctionsConstants.java
+++ b/components/camel-google-functions/src/main/java/org/apache/camel/component/google/functions/GoogleCloudFunctionsConstants.java
@@ -17,37 +17,9 @@
 package org.apache.camel.component.google.functions;
 
 public interface GoogleCloudFunctionsConstants {
-
     String OPERATION = "GoogleCloudFunctionsOperation";
-
-    // String S3_BUCKET = "CamelAwsLambdaS3Bucket";
-    // String S3_KEY = "CamelAwsLambdaS3Key";
-    // String S3_OBJECT_VERSION = "CamelAwsLambdaS3ObjectVersion";
-    // String ZIP_FILE = "CamelAwsLambdaZipFile";
-    // String DESCRIPTION = "CamelAwsLambdaDescription";
-    // String ROLE = "CamelAwsLambdaRole";
-    // String RUNTIME = "CamelAwsLambdaRuntime";
-    // String HANDLER = "CamelAwsLambdaHandler";
-    // String TARGET_ARN = "CamelAwsLambdaTargetArn";
-    // String MEMORY_SIZE = "CamelAwsLambdaMemorySize";
-    // String KMS_KEY_ARN = "CamelAwsLambdaKMSKeyArn";
-    // String ENVIRONMENT_VARIABLES = "CamelAwsLambdaEnvironmentVariables";
-    // String PUBLISH = "CamelAwsLambdaPublish";
-    // String TIMEOUT = "CamelAwsLambdaTimeout";
-    // String TAGS = "CamelAwsLambdaTags";
-    // String TRACING_CONFIG = "CamelAwsLambdaTracingConfig";
-    // String SECURITY_GROUP_IDS = "CamelAwsLambdaSecurityGroupIds";
-    // String SUBNET_IDS = "CamelAwsLambdaSubnetIds";
-    // String EVENT_SOURCE_ARN = "CamelAwsLambdaEventSourceArn";
-    // String EVENT_SOURCE_BATCH_SIZE = "CamelAwsLambdaEventSourceBatchSize";
-    // String EVENT_SOURCE_UUID = "CamelAwsLambdaEventSourceUuid";
-    // String RESOURCE_ARN = "CamelAwsLambdaResourceArn";
-    // String RESOURCE_TAGS = "CamelAwsLambdaResourceTags";
-    // String RESOURCE_TAG_KEYS = "CamelAwsLambdaResourceTagKeys";
-    // String VERSION_DESCRIPTION = "CamelAwsLambdaVersionDescription";
-    // String VERSION_REVISION_ID = "CamelAwsLambdaVersionRevisionId";
-    // String FUNCTION_VERSION = "CamelAwsLambdaFunctionVersion";
-    // String FUNCTION_ALIAS_NAME = "CamelAwsLambdaAliasFunctionName";
-    // String FUNCTION_ALIAS_DESCRIPTION = "CamelAwsLambdaAliasFunctionDescription";
-
+    String ENTRY_POINT = "GoogleCloudFunctionsEntryPoint";
+    String RUNTIME = "GoogleCloudFunctionsRuntime";
+    String SOURCE_ARCHIVE_URL = "GoogleCloudFunctionsSourceArchiveUrl";
+    String RESPONSE_OBJECT = "GoogleCloudFunctionsResponseObject";
 }
diff --git a/components/camel-google-functions/src/main/java/org/apache/camel/component/google/functions/GoogleCloudFunctionsProducer.java b/components/camel-google-functions/src/main/java/org/apache/camel/component/google/functions/GoogleCloudFunctionsProducer.java
index 663eb35..2cd854c 100644
--- a/components/camel-google-functions/src/main/java/org/apache/camel/component/google/functions/GoogleCloudFunctionsProducer.java
+++ b/components/camel-google-functions/src/main/java/org/apache/camel/component/google/functions/GoogleCloudFunctionsProducer.java
@@ -33,6 +33,7 @@ import com.google.cloud.functions.v1.GenerateDownloadUrlRequest;
 import com.google.cloud.functions.v1.GenerateDownloadUrlResponse;
 import com.google.cloud.functions.v1.GenerateUploadUrlRequest;
 import com.google.cloud.functions.v1.GenerateUploadUrlResponse;
+import com.google.cloud.functions.v1.HttpsTrigger;
 import com.google.cloud.functions.v1.ListFunctionsRequest;
 import com.google.cloud.functions.v1.LocationName;
 import com.google.cloud.functions.v1.UpdateFunctionRequest;
@@ -97,9 +98,9 @@ public class GoogleCloudFunctionsProducer extends DefaultProducer {
                 ListFunctionsPagedResponse pagedListResponse;
                 try {
                     pagedListResponse = client.listFunctions((ListFunctionsRequest) payload);
-                    List<CloudFunction> result = Lists.newArrayList(pagedListResponse.iterateAll());
+                    List<CloudFunction> response = Lists.newArrayList(pagedListResponse.iterateAll());
                     Message message = getMessageForResponse(exchange);
-                    message.setBody(result);
+                    message.setBody(response);
                 } catch (ApiException ae) {
                     LOG.trace("listFunctions command returned the error code {}", ae.getStatusCode());
                     throw ae;
@@ -112,9 +113,9 @@ public class GoogleCloudFunctionsProducer extends DefaultProducer {
                     .setPageSize(883849137) // TODO check it
                     .setPageToken("pageToken873572522").build();
             ListFunctionsPagedResponse pagedListResponse = client.listFunctions(request);
-            List<CloudFunction> result = Lists.newArrayList(pagedListResponse.iterateAll());
+            List<CloudFunction> response = Lists.newArrayList(pagedListResponse.iterateAll());
             Message message = getMessageForResponse(exchange);
-            message.setBody(result);
+            message.setBody(response);
         }
     }
 
@@ -122,22 +123,22 @@ public class GoogleCloudFunctionsProducer extends DefaultProducer {
         if (getConfiguration().isPojoRequest()) {
             Object payload = exchange.getIn().getMandatoryBody();
             if (payload instanceof CloudFunctionName) {
-                CloudFunction result;
+                CloudFunction response;
                 try {
-                    result = client.getFunction((CloudFunctionName) payload);
+                    response = client.getFunction((CloudFunctionName) payload);
                 } catch (ApiException ae) {
                     LOG.trace("getFunction command returned the error code {}", ae.getStatusCode());
                     throw ae;
                 }
                 Message message = getMessageForResponse(exchange);
-                message.setBody(result);
+                message.setBody(response);
             }
         } else {
             CloudFunctionName cfName = CloudFunctionName.of(getConfiguration().getProject(),
                     getConfiguration().getLocation(), getConfiguration().getFunctionName());
-            CloudFunction result = client.getFunction(cfName);
+            CloudFunction response = client.getFunction(cfName);
             Message message = getMessageForResponse(exchange);
-            message.setBody(result);
+            message.setBody(response);
         }
     }
 
@@ -145,11 +146,12 @@ public class GoogleCloudFunctionsProducer extends DefaultProducer {
         if (getConfiguration().isPojoRequest()) {
             Object payload = exchange.getIn().getMandatoryBody();
             if (payload instanceof CallFunctionRequest) {
-                CallFunctionResponse result;
+                CallFunctionResponse response;
                 try {
-                    result = client.callFunction((CallFunctionRequest) payload);
+                    response = client.callFunction((CallFunctionRequest) payload);
                     Message message = getMessageForResponse(exchange);
-                    message.setBody(result);
+                    message.setHeader(GoogleCloudFunctionsConstants.RESPONSE_OBJECT, response);
+                    message.setBody(response.getResult());
                 } catch (ApiException ae) {
                     LOG.trace("callFunction command returned the error code {}", ae.getStatusCode());
                     throw ae;
@@ -161,9 +163,10 @@ public class GoogleCloudFunctionsProducer extends DefaultProducer {
                     getConfiguration().getLocation(), getConfiguration().getFunctionName());
             CallFunctionRequest request = CallFunctionRequest.newBuilder().setName(cfName.toString()).setData(data)
                     .build();
-            CallFunctionResponse result = client.callFunction(request);
+            CallFunctionResponse response = client.callFunction(request);
             Message message = getMessageForResponse(exchange);
-            message.setBody(result);
+            message.setHeader(GoogleCloudFunctionsConstants.RESPONSE_OBJECT, response);
+            message.setBody(response.getResult());
         }
     }
 
@@ -173,10 +176,11 @@ public class GoogleCloudFunctionsProducer extends DefaultProducer {
             Object payload = exchange.getIn().getMandatoryBody();
             if (payload instanceof GenerateDownloadUrlRequest) {
                 try {
-                    GenerateDownloadUrlResponse result = client
+                    GenerateDownloadUrlResponse response = client
                             .generateDownloadUrl((GenerateDownloadUrlRequest) payload);
                     Message message = getMessageForResponse(exchange);
-                    message.setBody(result);
+                    message.setHeader(GoogleCloudFunctionsConstants.RESPONSE_OBJECT, response);
+                    message.setBody(response.getDownloadUrl());
                 } catch (ApiException ae) {
                     LOG.trace("generateDownloadUrl command returned the error code {}", ae.getStatusCode());
                     throw ae;
@@ -187,9 +191,10 @@ public class GoogleCloudFunctionsProducer extends DefaultProducer {
                     getConfiguration().getLocation(), getConfiguration().getFunctionName());
             GenerateDownloadUrlRequest request = GenerateDownloadUrlRequest.newBuilder().setName(cfName.toString())
                     .build();
-            GenerateDownloadUrlResponse result = client.generateDownloadUrl(request);
+            GenerateDownloadUrlResponse response = client.generateDownloadUrl(request);
             Message message = getMessageForResponse(exchange);
-            message.setBody(result);
+            message.setHeader(GoogleCloudFunctionsConstants.RESPONSE_OBJECT, response);
+            message.setBody(response.getDownloadUrl());
         }
     }
 
@@ -199,9 +204,10 @@ public class GoogleCloudFunctionsProducer extends DefaultProducer {
             Object payload = exchange.getIn().getMandatoryBody();
             if (payload instanceof GenerateUploadUrlRequest) {
                 try {
-                    GenerateUploadUrlResponse result = client.generateUploadUrl((GenerateUploadUrlRequest) payload);
+                    GenerateUploadUrlResponse response = client.generateUploadUrl((GenerateUploadUrlRequest) payload);
                     Message message = getMessageForResponse(exchange);
-                    message.setBody(result);
+                    message.setHeader(GoogleCloudFunctionsConstants.RESPONSE_OBJECT, response);
+                    message.setBody(response.getUploadUrl());
                 } catch (ApiException ae) {
                     LOG.trace("generateUploadUrl command returned the error code {}", ae.getStatusCode());
                     throw ae;
@@ -212,9 +218,10 @@ public class GoogleCloudFunctionsProducer extends DefaultProducer {
                     getConfiguration().getLocation());
             GenerateUploadUrlRequest request = GenerateUploadUrlRequest.newBuilder().setParent(locationName.toString())
                     .build();
-            GenerateUploadUrlResponse result = client.generateUploadUrl(request);
+            GenerateUploadUrlResponse response = client.generateUploadUrl(request);
             Message message = getMessageForResponse(exchange);
-            message.setBody(result);
+            message.setHeader(GoogleCloudFunctionsConstants.RESPONSE_OBJECT, response);
+            message.setBody(response.getUploadUrl());
         }
     }
 
@@ -224,16 +231,37 @@ public class GoogleCloudFunctionsProducer extends DefaultProducer {
             Object payload = exchange.getIn().getMandatoryBody();
             if (payload instanceof CreateFunctionRequest) {
                 try {
-                    CloudFunction result = client.createFunctionAsync((CreateFunctionRequest) payload).get();
+                    CloudFunction response = client.createFunctionAsync((CreateFunctionRequest) payload).get();
                     Message message = getMessageForResponse(exchange);
-                    message.setBody(result);
+                    message.setBody(response);
                 } catch (ApiException ae) {
                     LOG.trace("createFunction command returned the error code {}", ae.getStatusCode());
                     throw ae;
                 }
             }
         } else {
-            throw new IllegalArgumentException("createFunction is supported only in pojo mode");
+            final String project = getConfiguration().getProject();
+            final String location = getConfiguration().getLocation();
+            final String functionName = getConfiguration().getFunctionName();
+            final String entryPoint = exchange.getIn().getHeader(GoogleCloudFunctionsConstants.ENTRY_POINT, String.class);
+            final String runtime = exchange.getIn().getHeader(GoogleCloudFunctionsConstants.RUNTIME, String.class);
+            final String sourceArchiveUrl
+                    = exchange.getIn().getHeader(GoogleCloudFunctionsConstants.SOURCE_ARCHIVE_URL, String.class);
+
+            CloudFunction function = CloudFunction.newBuilder()
+                    .setName(CloudFunctionName.of(project, location, functionName).toString())
+                    .setEntryPoint(entryPoint)
+                    .setRuntime(runtime)
+                    .setHttpsTrigger(HttpsTrigger.getDefaultInstance())
+                    .setSourceArchiveUrl(sourceArchiveUrl)
+                    .build();
+            CreateFunctionRequest request = CreateFunctionRequest.newBuilder()
+                    .setLocation(LocationName.of(project, location).toString())
+                    .setFunction(function).build();
+
+            CloudFunction response = client.createFunctionAsync(request).get();
+            Message message = getMessageForResponse(exchange);
+            message.setBody(response);
         }
     }
 
@@ -243,9 +271,9 @@ public class GoogleCloudFunctionsProducer extends DefaultProducer {
             Object payload = exchange.getIn().getMandatoryBody();
             if (payload instanceof UpdateFunctionRequest) {
                 try {
-                    CloudFunction result = client.updateFunctionAsync((UpdateFunctionRequest) payload).get();
+                    CloudFunction response = client.updateFunctionAsync((UpdateFunctionRequest) payload).get();
                     Message message = getMessageForResponse(exchange);
-                    message.setBody(result);
+                    message.setBody(response);
                 } catch (ApiException ae) {
                     LOG.trace("updateFunction command returned the error code {}", ae.getStatusCode());
                     throw ae;
@@ -262,9 +290,9 @@ public class GoogleCloudFunctionsProducer extends DefaultProducer {
             Object payload = exchange.getIn().getMandatoryBody();
             if (payload instanceof DeleteFunctionRequest) {
                 try {
-                    Empty result = client.deleteFunctionAsync((DeleteFunctionRequest) payload).get();
+                    Empty response = client.deleteFunctionAsync((DeleteFunctionRequest) payload).get();
                     Message message = getMessageForResponse(exchange);
-                    message.setBody(result);
+                    message.setBody(response);
                 } catch (ApiException ae) {
                     LOG.trace("deleteFunction command returned the error code {}", ae.getStatusCode());
                     throw ae;
@@ -274,9 +302,9 @@ public class GoogleCloudFunctionsProducer extends DefaultProducer {
             CloudFunctionName cfName = CloudFunctionName.of(getConfiguration().getProject(),
                     getConfiguration().getLocation(), getConfiguration().getFunctionName());
             DeleteFunctionRequest request = DeleteFunctionRequest.newBuilder().setName(cfName.toString()).build();
-            Empty result = client.deleteFunctionAsync(request).get();
+            Empty response = client.deleteFunctionAsync(request).get();
             Message message = getMessageForResponse(exchange);
-            message.setBody(result);
+            message.setBody(response);
         }
     }
 
diff --git a/components/camel-google-functions/src/test/java/org/apache/camel/component/google/functions/integration/ComplexIntegrationTest.java b/components/camel-google-functions/src/test/java/org/apache/camel/component/google/functions/integration/ComplexIntegrationTest.java
deleted file mode 100644
index 3861550..0000000
--- a/components/camel-google-functions/src/test/java/org/apache/camel/component/google/functions/integration/ComplexIntegrationTest.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.camel.component.google.functions.integration;
-
-import org.apache.camel.EndpointInject;
-import org.apache.camel.ProducerTemplate;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.test.junit5.CamelTestSupport;
-import org.junit.jupiter.api.Test;
-
-public class ComplexIntegrationTest extends CamelTestSupport {
-
-    @EndpointInject
-    private ProducerTemplate template;
-
-    @EndpointInject("mock:bucket1")
-    private MockEndpoint mockBucket1;
-
-    @EndpointInject("mock:bucket2")
-    private MockEndpoint mockBucket2;
-
-    @EndpointInject("mock:processed")
-    private MockEndpoint mockProcessed;
-
-    @Override
-    protected RouteBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                // final int numberOfObjects = 3;
-                //final String serviceAccountKeyFile = "somefile.json";
-                // final String serviceAccountKeyFile = System.getenv("GOOGLE_APPLICATION_CREDENTIALS");
-
-                // //upload 3 file into bucket1
-                // byte[] payload = "Camel rocks!".getBytes();
-                // ByteArrayInputStream bais = new ByteArrayInputStream(payload);
-                // from("timer:timer1?repeatCount=" + numberOfObjects)
-                //         .process(exchange -> {
-                //             String filename = "file_" + ((int) (Math.random() * 10000)) + ".txt";
-                //             exchange.getIn().setHeader(GoogleCloudStorageConstants.OBJECT_NAME, filename);
-                //             exchange.getIn().setBody(bais);
-                //         })
-                //         .to("google-storage://" + bucket1 + "?serviceAccountKey=" + serviceAccountKeyFile)
-                //         .log("upload file object:${header.CamelGoogleCloudStorageObjectName}, body:${body}")
-                //         .to("mock:bucket1");
-
-                // //poll from bucket1, moving processed into bucket_processed and deleting original
-                // from("google-storage://" + bucket1 + "?serviceAccountKey=" + serviceAccountKeyFile
-                //      + "&moveAfterRead=true"
-                //      + "&destinationBucket=" + bucket3
-                //      + "&autoCreateBucket=true"
-                //      + "&deleteAfterRead=true"
-                //      + "&includeBody=true")
-                //              .log("consuming: ${header.CamelGoogleCloudStorageBucketName}/${header.CamelGoogleCloudStorageObjectName}")
-                //              .to("direct:processed")
-                //              .to("mock:processed");
-
-                // //upload these files to bucket2 
-                // from("direct:processed")
-                //         .to("google-storage://" + bucket2 + "?serviceAccountKey=" + serviceAccountKeyFile)
-                //         .log("uploaded file object:${header.CamelGoogleCloudStorageObjectName}, body:${body}")
-                //         .process(exchange -> {
-                //             exchange.getIn().setHeader(GoogleCloudStorageConstants.DOWNLOAD_LINK_EXPIRATION_TIME, 86400000L); //1 day
-                //         })
-                //         .to("google-storage://" + bucket2 + "?serviceAccountKey=" + serviceAccountKeyFile
-                //             + "&operation=createDownloadLink")
-                //         .log("URL for ${header.CamelGoogleCloudStorageBucketName}/${header.CamelGoogleCloudStorageObjectName} =${body}")
-                //         .to("mock:bucket2");
-
-                // //list all buckets
-                // from("timer:timer1?repeatCount=1&fixedRate=true&period=10000")
-                //         .to("google-storage://" + bucket2 + "?serviceAccountKey=" + serviceAccountKeyFile
-                //             + "&operation=listBuckets")
-                //         .log("list buckets:${body}");
-
-                // //list all object of the bucket2 and send result to direct:moreinfo and direct:copy
-                // from("timer:timer1?repeatCount=1&fixedRate=true&period=10000")
-                //         .to("google-storage://" + bucket2 + "?serviceAccountKey=" + serviceAccountKeyFile
-                //             + "&operation=listObjects")
-                //         .log("list " + bucket2 + " objects body:${body}")
-                //         .split(bodyAs(List.class))
-                //         .log("splitted: ${body}")
-                //         .multicast().to("direct:moreinfo", "direct:copy");
-
-                // from("direct:moreinfo")
-                //         .process(exchange -> {
-                //             Blob blob = exchange.getIn().getBody(Blob.class);
-                //             String fileName = blob.getName();
-                //             exchange.getIn().setHeader(GoogleCloudStorageConstants.OBJECT_NAME, fileName);
-                //         })
-                //         .to("google-storage://" + bucket2 + "?serviceAccountKey=" + serviceAccountKeyFile
-                //             + "&operation=getObject")
-                //         .log("get object bucket:${header.CamelGoogleCloudStorageBucketName} object:${header.CamelGoogleCloudStorageObjectName}, body:${body}");
-
-                // //copy object
-                // from("direct:copy")
-                //         .process(exchange -> {
-                //             Blob blob = exchange.getIn().getBody(Blob.class);
-                //             String fileName = blob.getName();
-                //             String copyFileName = "copy_" + fileName;
-                //             exchange.getIn().setHeader(GoogleCloudStorageConstants.OBJECT_NAME, fileName);
-                //             exchange.getIn().setHeader(GoogleCloudStorageConstants.DESTINATION_BUCKET_NAME, bucket4);
-                //             exchange.getIn().setHeader(GoogleCloudStorageConstants.DESTINATION_OBJECT_NAME, copyFileName);
-                //         })
-                //         .to("google-storage://" + bucket2 + "?serviceAccountKey=" + serviceAccountKeyFile
-                //             + "&operation=copyObject")
-                //         .log("${body}");
-
-            }
-        };
-    }
-
-    @Test
-    public void sendIn() throws Exception {
-        mockBucket1.expectedMessageCount(3);
-        mockBucket2.expectedMessageCount(3);
-        mockProcessed.expectedMessageCount(3);
-
-        Thread.sleep(10000);
-        assertMockEndpointsSatisfied();
-    }
-
-}
diff --git a/components/camel-google-functions/src/test/java/org/apache/camel/component/google/functions/integration/IntegrationTest.java b/components/camel-google-functions/src/test/java/org/apache/camel/component/google/functions/integration/IntegrationTest.java
new file mode 100644
index 0000000..560d154
--- /dev/null
+++ b/components/camel-google-functions/src/test/java/org/apache/camel/component/google/functions/integration/IntegrationTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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.camel.component.google.functions.integration;
+
+import java.util.List;
+
+import com.google.cloud.functions.v1.CloudFunction;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.google.functions.GoogleCloudFunctionsConstants;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+public class IntegrationTest extends CamelTestSupport {
+
+    final String functionNameReverseString = "function-reverse-string";
+    final String serviceAccountKeyFile = System.getenv("GOOGLE_APPLICATION_CREDENTIALS");
+    final String project = "myProject";
+    final String location = "us-central1";
+    final String functionCreationEntryPoint = "com.example.Example";
+    final String functionCreationSourceCode = "gs://myCamelBucket/function-source.zip";
+
+    @EndpointInject("mock:functionsList1")
+    private MockEndpoint mockFunctionList1;
+    @EndpointInject("mock:getFunction")
+    private MockEndpoint mockGetFunction;
+    @EndpointInject("mock:generateDownloadUrl")
+    private MockEndpoint mockGenerateDownloadUrl;
+    @EndpointInject("mock:callFunction")
+    private MockEndpoint mockCallFunction;
+    @EndpointInject("mock:createFunction")
+    private MockEndpoint mockCreateFunction;
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+
+                // list functions
+                from("timer:timer1?repeatCount=1")
+                        .to("google-functions://" + functionNameReverseString + "?serviceAccountKey="
+                            + serviceAccountKeyFile + "&project=" + project + "&location=" + location
+                            + "&operation=listFunctions")
+                        .log("body:${body}").split(bodyAs(List.class)).process(exchange -> {
+                            CloudFunction cf = exchange.getIn().getBody(CloudFunction.class);
+                            exchange.getIn().setBody(cf.getName());
+                        }).to("direct:directFunctionList1").to("mock:functionsList1");
+
+                // get function
+                from("direct:directFunctionList1").to("google-functions://" + functionNameReverseString
+                                                      + "?serviceAccountKey=" + serviceAccountKeyFile + "&project=" + project
+                                                      + "&location="
+                                                      + location + "&operation=getFunction")
+                        .log("body:${body}").to("direct:getFunction").to("mock:getFunction");
+
+                // generate download url
+                from("timer:timer1?repeatCount=1").to("google-functions://" + functionNameReverseString
+                                                      + "?serviceAccountKey=" + serviceAccountKeyFile + "&project=" + project
+                                                      + "&location="
+                                                      + location + "&operation=generateDownloadUrl")
+                        .log("body:${body}").to("mock:generateDownloadUrl");
+
+                // call function
+                from("timer:timer1?repeatCount=1").process(exchange -> {
+                    exchange.getIn().setBody("just a message");
+                }).to("google-functions://" + functionNameReverseString + "?serviceAccountKey=" + serviceAccountKeyFile
+                      + "&project=" + project + "&location=" + location + "&operation=callFunction")
+                        .log("body:${body}").to("mock:callFunction");
+
+                // create function
+                final String randomFunctionName = createRandomFunctionName();
+                from("timer:timer1?repeatCount=1").process(exchange -> {
+                    exchange.getIn().setHeader(GoogleCloudFunctionsConstants.ENTRY_POINT, functionCreationEntryPoint);
+                    exchange.getIn().setHeader(GoogleCloudFunctionsConstants.RUNTIME, "java11");
+                    exchange.getIn().setHeader(GoogleCloudFunctionsConstants.SOURCE_ARCHIVE_URL,
+                            functionCreationSourceCode);
+                }).to("google-functions://" + randomFunctionName + "?serviceAccountKey=" + serviceAccountKeyFile
+                      + "&project=" + project + "&location=" + location + "&operation=createFunction")
+                        .process(exchange -> {
+                        }).log("body:${body}").to("mock:createFunction");
+
+                // delete function
+                from("timer:timer1?repeatCount=1")
+                        .to("google-functions://" + "randomFunction_0" + "?serviceAccountKey=" + serviceAccountKeyFile
+                            + "&project=" + project + "&location=" + location + "&operation=deleteFunction")
+                        .log("body:${body}");
+
+            }
+        };
+    }
+
+    @Test
+    public void sendIn() throws Exception {
+        mockFunctionList1.expectedMinimumMessageCount(1);
+        mockGenerateDownloadUrl.expectedMessageCount(1);
+        mockCallFunction.expectedMessageCount(1);
+        mockCreateFunction.expectedMessageCount(1);
+
+        Thread.sleep(10000);
+        int functionListCounter = mockFunctionList1.getReceivedCounter();
+        mockGetFunction.expectedMessageCount(functionListCounter);
+
+        assertMockEndpointsSatisfied();
+    }
+
+    private String createRandomFunctionName() {
+        int r = (int) (Math.random() * 10000);
+        return "randomFunction_" + r;
+    }
+
+}
diff --git a/components/camel-google-functions/src/test/java/org/apache/camel/component/google/functions/unit/GoogleCloudFunctionsComponentTest.java b/components/camel-google-functions/src/test/java/org/apache/camel/component/google/functions/unit/GoogleCloudFunctionsComponentTest.java
index 7e0e4ba..3270f38 100644
--- a/components/camel-google-functions/src/test/java/org/apache/camel/component/google/functions/unit/GoogleCloudFunctionsComponentTest.java
+++ b/components/camel-google-functions/src/test/java/org/apache/camel/component/google/functions/unit/GoogleCloudFunctionsComponentTest.java
@@ -49,6 +49,7 @@ import org.apache.camel.EndpointInject;
 import org.apache.camel.Exchange;
 import org.apache.camel.ExchangePattern;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.google.functions.GoogleCloudFunctionsConstants;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
@@ -261,8 +262,9 @@ public class GoogleCloudFunctionsComponentTest extends GoogleCloudFunctionsBaseT
 
     @Test
     public void callFunctionTest() throws Exception {
+        final String result = "result-934426595";
         CallFunctionResponse expectedResponse = CallFunctionResponse.newBuilder()
-                .setExecutionId("executionId-454906285").setResult("result-934426595")
+                .setExecutionId("executionId-454906285").setResult(result)
                 .setError("error96784904").build();
         mockCloudFunctionsService.addResponse(expectedResponse);
 
@@ -272,7 +274,9 @@ public class GoogleCloudFunctionsComponentTest extends GoogleCloudFunctionsBaseT
         Exchange exchange = template.send("direct:callFunction", ExchangePattern.InOut, exc -> {
             exc.getIn().setBody(data);
         });
-        CallFunctionResponse actualResponse = exchange.getMessage().getBody(CallFunctionResponse.class);
+        assertEquals(result, exchange.getMessage().getBody(String.class));
+        CallFunctionResponse actualResponse
+                = exchange.getMessage().getHeader(GoogleCloudFunctionsConstants.RESPONSE_OBJECT, CallFunctionResponse.class);
         assertEquals(expectedResponse, actualResponse);
 
         List<AbstractMessage> actualRequests = mockCloudFunctionsService.getRequests();
@@ -287,8 +291,9 @@ public class GoogleCloudFunctionsComponentTest extends GoogleCloudFunctionsBaseT
 
     @Test
     public void callFunctionPojoTest() throws Exception {
+        final String result = "result-934426595";
         CallFunctionResponse expectedResponse = CallFunctionResponse.newBuilder()
-                .setExecutionId("executionId-454906285").setResult("result-934426595")
+                .setExecutionId("executionId-454906285").setResult(result)
                 .setError("error96784904").build();
         mockCloudFunctionsService.addResponse(expectedResponse);
 
@@ -300,7 +305,9 @@ public class GoogleCloudFunctionsComponentTest extends GoogleCloudFunctionsBaseT
         Exchange exchange = template.send("direct:callFunctionPojo", ExchangePattern.InOut, exc -> {
             exc.getIn().setBody(request);
         });
-        CallFunctionResponse actualResponse = exchange.getMessage().getBody(CallFunctionResponse.class);
+        assertEquals(result, exchange.getMessage().getBody(String.class));
+        CallFunctionResponse actualResponse
+                = exchange.getMessage().getHeader(GoogleCloudFunctionsConstants.RESPONSE_OBJECT, CallFunctionResponse.class);
         assertEquals(expectedResponse, actualResponse);
 
         List<AbstractMessage> actualRequests = mockCloudFunctionsService.getRequests();
@@ -315,16 +322,18 @@ public class GoogleCloudFunctionsComponentTest extends GoogleCloudFunctionsBaseT
 
     @Test
     public void generateDownloadUrlTest() throws Exception {
+        String downloadUrl = "downloadUrl-1211148345";
         CloudFunctionName cfName = CloudFunctionName.of(project, location, functionName);
 
         GenerateDownloadUrlResponse expectedResponse = GenerateDownloadUrlResponse.newBuilder()
-                .setDownloadUrl("downloadUrl-1211148345").build();
+                .setDownloadUrl(downloadUrl).build();
         mockCloudFunctionsService.addResponse(expectedResponse);
 
         Exchange exchange = template.send("direct:generateDownloadUrl", ExchangePattern.InOut, exc -> {
         });
+        assertEquals(downloadUrl, exchange.getMessage().getBody(String.class));
         GenerateDownloadUrlResponse actualResponse = exchange.getMessage()
-                .getBody(GenerateDownloadUrlResponse.class);
+                .getHeader(GoogleCloudFunctionsConstants.RESPONSE_OBJECT, GenerateDownloadUrlResponse.class);
         assertEquals(expectedResponse, actualResponse);
 
         List<AbstractMessage> actualRequests = mockCloudFunctionsService.getRequests();
@@ -336,10 +345,11 @@ public class GoogleCloudFunctionsComponentTest extends GoogleCloudFunctionsBaseT
 
     @Test
     public void generateDownloadUrlPojoTest() throws Exception {
+        String downloadUrl = "downloadUrl-1211148345";
         CloudFunctionName cfName = CloudFunctionName.of(project, location, functionName);
 
         GenerateDownloadUrlResponse expectedResponse = GenerateDownloadUrlResponse.newBuilder()
-                .setDownloadUrl("downloadUrl-1211148345").build();
+                .setDownloadUrl(downloadUrl).build();
         mockCloudFunctionsService.addResponse(expectedResponse);
 
         GenerateDownloadUrlRequest request = GenerateDownloadUrlRequest.newBuilder().setName(cfName.toString())
@@ -348,8 +358,10 @@ public class GoogleCloudFunctionsComponentTest extends GoogleCloudFunctionsBaseT
         Exchange exchange = template.send("direct:generateDownloadUrlPojo", ExchangePattern.InOut, exc -> {
             exc.getIn().setBody(request);
         });
+
+        assertEquals(downloadUrl, exchange.getMessage().getBody(String.class));
         GenerateDownloadUrlResponse actualResponse = exchange.getMessage()
-                .getBody(GenerateDownloadUrlResponse.class);
+                .getHeader(GoogleCloudFunctionsConstants.RESPONSE_OBJECT, GenerateDownloadUrlResponse.class);
         assertEquals(expectedResponse, actualResponse);
 
         List<AbstractMessage> actualRequests = mockCloudFunctionsService.getRequests();
@@ -360,15 +372,17 @@ public class GoogleCloudFunctionsComponentTest extends GoogleCloudFunctionsBaseT
 
     @Test
     public void generateUploadUrlTest() throws Exception {
+        final String updloadUrl = "uploadUrl1239085998";
         LocationName locationName = LocationName.of(project, location);
         GenerateUploadUrlResponse expectedResponse = GenerateUploadUrlResponse.newBuilder()
-                .setUploadUrl("uploadUrl1239085998").build();
+                .setUploadUrl(updloadUrl).build();
         mockCloudFunctionsService.addResponse(expectedResponse);
 
         Exchange exchange = template.send("direct:generateUploadUrl", ExchangePattern.InOut, exc -> {
         });
+        assertEquals(updloadUrl, exchange.getMessage().getBody(String.class));
         GenerateUploadUrlResponse actualResponse = exchange.getMessage()
-                .getBody(GenerateUploadUrlResponse.class);
+                .getHeader(GoogleCloudFunctionsConstants.RESPONSE_OBJECT, GenerateUploadUrlResponse.class);
         assertEquals(expectedResponse, actualResponse);
 
         List<AbstractMessage> actualRequests = mockCloudFunctionsService.getRequests();
@@ -379,9 +393,10 @@ public class GoogleCloudFunctionsComponentTest extends GoogleCloudFunctionsBaseT
 
     @Test
     public void generateUploadUrlTestPojo() throws Exception {
+        final String updloadUrl = "uploadUrl1239085998";
         LocationName locationName = LocationName.of(project, location);
         GenerateUploadUrlResponse expectedResponse = GenerateUploadUrlResponse.newBuilder()
-                .setUploadUrl("uploadUrl1239085998").build();
+                .setUploadUrl(updloadUrl).build();
         mockCloudFunctionsService.addResponse(expectedResponse);
 
         GenerateUploadUrlRequest request = GenerateUploadUrlRequest.newBuilder()
@@ -389,8 +404,9 @@ public class GoogleCloudFunctionsComponentTest extends GoogleCloudFunctionsBaseT
         Exchange exchange = template.send("direct:generateUploadUrlPojo", ExchangePattern.InOut, exc -> {
             exc.getIn().setBody(request);
         });
+        assertEquals(updloadUrl, exchange.getMessage().getBody(String.class));
         GenerateUploadUrlResponse actualResponse = exchange.getMessage()
-                .getBody(GenerateUploadUrlResponse.class);
+                .getHeader(GoogleCloudFunctionsConstants.RESPONSE_OBJECT, GenerateUploadUrlResponse.class);
         assertEquals(expectedResponse, actualResponse);
 
         List<AbstractMessage> actualRequests = mockCloudFunctionsService.getRequests();
@@ -399,7 +415,6 @@ public class GoogleCloudFunctionsComponentTest extends GoogleCloudFunctionsBaseT
         assertEquals(locationName.toString(), actualRequest.getParent());
     }
 
-    @Disabled
     @Test
     public void createFunctionTest() throws Exception {
         CloudFunctionName cfName = CloudFunctionName.of(project, location, functionName);
@@ -417,6 +432,9 @@ public class GoogleCloudFunctionsComponentTest extends GoogleCloudFunctionsBaseT
                 .setResponse(Any.pack(expectedResponse)).build();
         mockCloudFunctionsService.addResponse(resultOperation);
         Exchange exchange = template.send("direct:createFunction", ExchangePattern.InOut, exc -> {
+            exc.getIn().setHeader(GoogleCloudFunctionsConstants.ENTRY_POINT, "com.example.Test");
+            exc.getIn().setHeader(GoogleCloudFunctionsConstants.RUNTIME, "java11");
+            exc.getIn().setHeader(GoogleCloudFunctionsConstants.SOURCE_ARCHIVE_URL, "gs://somebucket/file.zip");
         });
         CloudFunction actualResponse = exchange.getMessage().getBody(CloudFunction.class);
         assertEquals(expectedResponse, actualResponse);
diff --git a/components/camel-google-functions/src/test/resources/log4j.properties b/components/camel-google-functions/src/test/resources/log4j.properties
index 23e3d45..77d1f5d 100644
--- a/components/camel-google-functions/src/test/resources/log4j.properties
+++ b/components/camel-google-functions/src/test/resources/log4j.properties
@@ -20,7 +20,7 @@
 #
 appender.file.type = File
 appender.file.name = file
-appender.file.fileName = target/camel-google-storage-test.log
+appender.file.fileName = target/camel-google-functions-test.log
 appender.file.layout.type = PatternLayout
 appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
 appender.out.type = Console