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-k-examples.git
commit 34425ac930604be3d14e19d6bcd0b05d33d8b6a7 Author: Nicola Ferraro <[email protected]> AuthorDate: Wed May 13 00:43:57 2020 +0200 Add an API example --- 02-serverless-api/API.java | 44 +++++ 02-serverless-api/openapi.yaml | 53 ++++++ 02-serverless-api/readme.didact.md | 273 ++++++++++++++++++++++++++++ 02-serverless-api/readme.md | 1 + 02-serverless-api/s3.properties | 15 ++ 02-serverless-api/test/MinioCustomizer.java | 36 ++++ 02-serverless-api/test/crud.feature | 65 +++++++ 02-serverless-api/test/minio.properties | 15 ++ 02-serverless-api/test/minio.yaml | 71 ++++++++ 02-serverless-api/test/yaks-config.yaml | 14 ++ README.md | 1 + 11 files changed, 588 insertions(+) diff --git a/02-serverless-api/API.java b/02-serverless-api/API.java new file mode 100755 index 0000000..22d6b40 --- /dev/null +++ b/02-serverless-api/API.java @@ -0,0 +1,44 @@ +// camel-k: language=java + +import org.apache.camel.builder.AggregationStrategies; +import org.apache.camel.builder.RouteBuilder; + +public class API extends RouteBuilder { + @Override + public void configure() throws Exception { + + // All endpoints starting from "direct:..." reference an operationId defined + // in the "openapi.yaml" file. + + // List the object names available in the S3 bucket + from("direct:list") + .to("aws-s3://{{api.bucket}}?operation=listObjects") + .transform().simple("${body.objectSummaries}") + .split(simple("${body}"), AggregationStrategies.groupedBody()) + .transform().simple("${body.key}") + .end() + .marshal().json(); + + + // Get an object from the S3 bucket + from("direct:get") + .setHeader("CamelAwsS3Key", simple("${header.name}")) + .to("aws-s3://{{api.bucket}}?operation=getObject") + .setHeader("Content-Type", simple("${body.objectMetadata.contentType}")) + .transform().simple("${body.objectContent}"); + + + // Upload a new object into the S3 bucket + from("direct:create") + .setHeader("CamelAwsS3Key", simple("${header.name}")) + .to("aws-s3://{{api.bucket}}"); + + + // Delete an object from the S3 bucket + from("direct:delete") + .setHeader("CamelAwsS3Key", simple("${header.name}")) + .to("aws-s3://{{api.bucket}}?operation=deleteObject") + .setBody().constant(""); + + } +} diff --git a/02-serverless-api/openapi.yaml b/02-serverless-api/openapi.yaml new file mode 100644 index 0000000..42e9f6e --- /dev/null +++ b/02-serverless-api/openapi.yaml @@ -0,0 +1,53 @@ +--- +openapi: 3.0.2 +info: + title: Camel K Object API + version: 1.0.0 + description: A CRUD API for an object store +paths: + /: + get: + responses: + "200": + content: + application/json: + schema: + type: array + items: + type: string + description: Object list + operationId: list + summary: List the objects + /{name}: + get: + responses: + "200": + content: + application/octet-stream: {} + description: The object content + operationId: get + summary: Get the content of an object + put: + requestBody: + description: The object content + content: + application/octet-stream: {} + required: true + responses: + "200": + description: The object has been created + operationId: create + summary: Save an object + delete: + responses: + "204": + description: Object has been deleted + operationId: delete + summary: Delete an object + parameters: + - name: name + description: Name of the object + schema: + type: string + in: path + required: true diff --git a/02-serverless-api/readme.didact.md b/02-serverless-api/readme.didact.md new file mode 100644 index 0000000..1560cc5 --- /dev/null +++ b/02-serverless-api/readme.didact.md @@ -0,0 +1,273 @@ +# Camel K Serverless API Example + +This example demonstrates how to write an API based Camel K integration, from the design of the OpenAPI definition +to the implementation of the specific endpoints up to the deployment as serverless API in Knative. + +In this specific example, the API enables users to store generic objects, such as files, in a backend system, allowing all CRUD operation on them. + +The backend is an Amazon AWS S3 bucket that you might provide. In alternative, you'll be given instructions on how to +create a simple [Minio](https://min.io/) backend, which uses a S3 compatible protocol. + +## Before you begin + +Read the general instructions in the [root README.md file](../README.md) for setting up your environment and the Kubernetes cluster before looking at this example. + +Make sure you've read the [installation instructions](https://camel.apache.org/camel-k/latest/installation/installation.html) for your specific +cluster before starting the example. + +You should open this file with [Didact](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-didact) if available on your IDE. + +## Requirements + +<a href='didact://?commandId=vscode.didact.validateAllRequirements' title='Validate all requirements!'><button>Validate all Requirements at Once!</button></a> + +**Kubectl CLI** + +The Kubernetes `kubectl` CLI tool will be used to interact with the Kubernetes cluster. + +[Check if the Kubectl CLI is installed](didact://?commandId=vscode.didact.cliCommandSuccessful&text=kubectl-requirements-status$$kubectl%20help&completion=Checked%20kubectl%20tool%20availability "Tests to see if `kubectl help` returns a 0 return code"){.didact} + +*Status: unknown*{#kubectl-requirements-status} + +**Connection to a Kubernetes cluster** + +You need to connect to a Kubernetes cluster in order to run the example. + +[Check if you're connected to a Kubernetes cluster](didact://?commandId=vscode.didact.cliCommandSuccessful&text=cluster-requirements-status$$kubectl%20get%20pod&completion=Checked%20Kubernetes%20connection "Tests to see if `kubectl get pod` returns a 0 return code"){.didact} + +*Status: unknown*{#cluster-requirements-status} + +**Apache Camel K CLI ("kamel")** + +You need the Apache Camel K CLI ("kamel") in order to access all Camel K features. + +[Check if the Apache Camel K CLI ("kamel") is installed](didact://?commandId=vscode.didact.requirementCheck&text=kamel-requirements-status$$kamel%20version$$Camel%20K%20Client&completion=Checked%20if%20Camel%20K%20CLI%20is%20available%20on%20this%20system. "Tests to see if `kamel version` returns a result"){.didact} + +*Status: unknown*{#kamel-requirements-status} + +**Knative installed on the cluster** + +The cluster also needs to have Knative installed and working. Refer to the [official Knative documentation](https://knative.dev/docs/install/) for information on how to install it in your cluster. + +[Check if the Knative is installed](didact://?commandId=vscode.didact.requirementCheck&text=kservice-project-check$$kubectl%20api-resources%20--api-group=serving.knative.dev$$kservice%2Cksvc&completion=Verified%20Knative%20services%20installation. "Verifies if Knative is installed"){.didact} + +*Status: unknown*{#kservice-project-check} + +### Optional Requirements + +The following requirements are optional. They don't prevent the execution of the demo, but may make it easier to follow. + +**VS Code Extension Pack for Apache Camel** + +The VS Code Extension Pack for Apache Camel provides a collection of useful tools for Apache Camel K developers, +such as code completion and integrated lifecycle management. They are **recommended** for the tutorial, but they are **not** +required. + +You can install it from the VS Code Extensions marketplace. + +[Check if the VS Code Extension Pack for Apache Camel by Red Hat is installed](didact://?commandId=vscode.didact.extensionRequirementCheck&text=extension-requirement-status$$redhat.apache-camel-extension-pack&completion=Camel%20extension%20pack%20is%20available%20on%20this%20system. "Checks the VS Code workspace to make sure the extension pack is installed"){.didact} + +*Status: unknown*{#extension-requirement-status} + +## 1. Preparing the namespace + +Let's open a terminal and go to the example directory: + +``` +cd 02-serverless-api +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$cd%2002-serverless-api&completion=Executed%20command. "Opens a new terminal and sends the command above"){.didact}) + + +We're going to create a namespace named `camel-api` for running the example. To create it, execute the following command: + +``` +kubectl create namespace camel-api +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$kubectl%20create%20namespace%20camel-api&completion=New%20project%20creation. "Opens a new terminal and sends the command above"){.didact}) + + +Now we can set the `camel-api` namespace as default namespace for the following commands: + +``` +kubectl config set-context --current --namespace=camel-api +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$kubectl%20config%20set-context%20--current%20--namespace%3Dcamel-api&completion=New%20project%20creation. "Opens a new terminal and sends the command above"){.didact}) + +You need to install Camel K in the `camel-api` namespace (or globally in the whole cluster). +In many settings (e.g. OpenShift, CRC), it's sufficient to execute the following command to install Camel K: + +``` +kamel install +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$kamel%20install&completion=Installing%20Camel%20K. "Opens a new terminal and sends the command above"){.didact}) + +NOTE: The `kamel install` command requires some prerequisites to be successful in some situations, e.g. you need to enable the registry addon on Minikube. Refer to the [Camel K install guide](https://camel.apache.org/camel-k/latest/installation/installation.html) for cluster-specific instructions. + +To check that Camel K is installed we'll retrieve the IntegrationPlatform object from the namespace: + +``` +kubectl get integrationplatform +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$kubectl%20get%20integrationplatform&completion=Executed%20Command. "Opens a new terminal and sends the command above"){.didact}) + +You should find an IntegrationPlatform in status `Ready`. + +You can now proceed to the next section. + +## 2. Configuring the object storage backend + +You have two alternative options for setting up the S3 backend that will be used to store the objects via the Camel K API: +you can use an existing S3 bucket of your own or you can set up a local S3 compatible object storage. + +### 2.1 [Alternative 1] I don't have a S3 bucket: let's install a Minio backend + +The `test` directory contains an all-in-one configuration file for creating a Minio backend that will provide a S3 compatible protocol +for storing the objects. + +Open the ([test/minio.yaml](didact://?commandId=vscode.open&projectFilePath=test/minio.yaml "Opens the Minio configuration"){.didact}) file to check its content before applying. + +To create the minio backend, just apply the provided file: + +``` +kubectl apply -f test/minio.yaml +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$kubectl%20apply%20-f%20test/minio.yaml&completion=Created%20Minio%20backend. "Opens a new terminal and sends the command above"){.didact}) + +That's enough to have a test object storage to use with the API integration. + +### 2.1 [Alternative 2] I have a S3 bucket + +If you have a S3 bucket and you want to use it instead of the test backend, you can do it. The only +things that you need to provide are a **AWS Access Key ID and Secret** that you can obtain from the Amazon AWS console. + +Edit the ([s3.properties](didact://?commandId=vscode.open&projectFilePath=s3.properties "Opens the S3 configuration"){.didact}) to set the right value for the properties `camel.component.aws-s3.access-key` and `camel.component.aws-s3.secret-key`. +Those properties will be automatically injected into the Camel `aw3-s3` component. + +## 3. Designing the API + +An object store REST API is provided in the [openapi.yaml](didact://?commandId=vscode.open&projectFilePath=openapi.yaml "Opens the OpenAPI definition"){.didact} file. + +It contains operations for: +- Listing the name of the contained objects +- Creating a new object +- Getting the content of an object +- Deleting an object + +The file can be edited manually or better using an online editor, such as [Apicurio](https://studio.apicur.io/). + +## 4. Running the API integration + +The endpoints defined in the API can be implemented in a Camel K integration using a `direct:<operationId>` endpoint. +This has been implemented in the [API.java](didact://?commandId=vscode.open&projectFilePath=API.java "Opens the integration file"){.didact} file. + +To run the integration, you need to link it to the proper configuration, that depends on what configuration you've chosen. + +### 4.1 [Alternative 1] Using the test Minio server + +As alternative, to connect the integration to the **test Minio server** deployed before using the [test/MinioCustomizer.java](didact://?commandId=vscode.open&projectFilePath=test/MinioCustomizer.java "Opens the customizer file"){.didact} class: + +``` +kamel run --name api test/MinioCustomizer.java API.java --property-file test/minio.properties --open-api openapi.yaml -d camel-openapi-java +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$kamel%20run%20--name%20api%20test/MinioCustomizer.java%20API.java%20--property-file%20test/minio.properties%20--open-api%20openapi.yaml%20-d%20camel-openapi-java&completion=Integration%20run. "Opens a new terminal and sends the command above"){.didact}) + +### 4.2 [Alternative 2] Using the S3 service + +To connect the integration to the **AWS S3 service**: + +``` +kamel run API.java --property-file s3.properties --open-api openapi.yaml -d camel-openapi-java +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$kamel%20run%20API.java%20--property-file%20s3.properties%20--open-api%20openapi.yaml%20-d%20camel-openapi-java&completion=Integration%20run. "Opens a new terminal and sends the command above"){.didact}) + + +## 5. Using the API + +After running the integration API, you should be able to call the API endpoints to check its behavior. + +Make sure the integration is running, by checking its status: + +``` +kubectl get integrations +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$kubectl%20get%20integrations&completion=Getting%20running%20integrations. "Opens a new terminal and sends the command above"){.didact}) + +An integration named `api` should be present in the list and it should be in status `Running`. There's also a `kamel get` command which is an alternative way to list all running integrations. + +NOTE: it may take some time, the first time you run the integration, for it to reach the `Running` state. + +After the integraiton has reached the running state, you can get the route corresponding to it via the following command: + +``` +URL=$(kubectl get routes.serving.knative.dev api -o jsonpath='{.status.url}') +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$URL%3D%24%28kubectl%20get%20routes.serving.knative.dev%20api%20-o%20jsonpath%3D%27%7B.status.url%7D%27%29&completion=Getting%20route. "Opens a new terminal and sends the command above"){.didact}) + +You can print the route to check if it's correct: + +``` +echo $URL +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$echo%20$URL&completion=Print%20route. "Opens a new terminal and sends the command above"){.didact}) + +NOTE: ensure that you've followed all the instructions in the Knative documentation during installation, especially the DNS part is fundamental for being able to contact the API. + +You can now play with it! What follows is a list of commands that you can run to use the API and check if it's working. + +Get the list of objects: +``` +curl -i $URL/ +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$curl%20-i%20$URL&completion=Use%20the%20API. "Opens a new terminal and sends the command above"){.didact}) + +Looking at the pods, you should find a pod corresponding to the API integration: + +``` +kubectl get pods +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$kubectl%20get%20pods&completion=Getting%20running%20pods. "Opens a new terminal and sends the command above"){.didact}) + +If you wait **at least one minute** without invoking the API, you'll find that the pod will disappear. +Calling the API again will make the pod appear to serve the request. This is done to save resources and it's one the main features of Knative Serving. + +You can continue with other commands. + +Upload an object: +``` +curl -i -X PUT --header "Content-Type: application/octet-stream" --data-binary "@API.java" $URL/example +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$curl%20-i%20-X%20PUT%20--header%20%22Content-Type%3A%20application%2Foctet-stream%22%20--data-binary%20%22%40API.java%22%20%24URL%2Fexample&completion=Use%20the%20API. "Opens a new terminal and sends the command above"){.didact}) + +Get the new list of objects: +``` +curl -i $URL/ +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$curl%20-i%20$URL&completion=Use%20the%20API. "Opens a new terminal and sends the command above"){.didact}) + +Get the content of a file: +``` +curl -i $URL/example +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$curl%20-i%20%24URL%2Fexample&completion=Use%20the%20API. "Opens a new terminal and sends the command above"){.didact}) + +Delete the file: +``` +curl -i -X DELETE $URL/example +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$curl%20-i%20-X%20DELETE%20%24URL%2Fexample&completion=Use%20the%20API. "Opens a new terminal and sends the command above"){.didact}) + +Get (again) the new list of objects: +``` +curl -i $URL/ +``` +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$curl%20-i%20$URL&completion=Use%20the%20API. "Opens a new terminal and sends the command above"){.didact}) + + +## 8. Uninstall + +To cleanup everything, execute the following command: + +```kubectl delete namespace camel-api``` + +([^ execute](didact://?commandId=vscode.didact.sendNamedTerminalAString&text=camelTerm$$kubectl%20delete%20namespace%20camel-api&completion=Removed%20the%20project%20from%20the%20cluster. "Cleans up the cluster after running the example"){.didact}) diff --git a/02-serverless-api/readme.md b/02-serverless-api/readme.md new file mode 120000 index 0000000..c0bf82f --- /dev/null +++ b/02-serverless-api/readme.md @@ -0,0 +1 @@ +readme.didact.md \ No newline at end of file diff --git a/02-serverless-api/s3.properties b/02-serverless-api/s3.properties new file mode 100644 index 0000000..8b5feeb --- /dev/null +++ b/02-serverless-api/s3.properties @@ -0,0 +1,15 @@ +# S3 Configuration + +# This configuration should not be kept together with the source code in production. + +# Bucket (referenced in the routes) +api.bucket=camel-k +# Region of the buket +camel.component.aws-s3.region=EU_WEST_1 +# AWS Access Key ID +camel.component.aws-s3.access-key=<put-your-aws-access-key-id-here> +# AWS Access Key Secret +camel.component.aws-s3.secret-key=<put-your-aws-access-key-secret-here> + +# General configuration +camel.context.rest-configuration.api-context-path=/openapi.json diff --git a/02-serverless-api/test/MinioCustomizer.java b/02-serverless-api/test/MinioCustomizer.java new file mode 100644 index 0000000..ff59716 --- /dev/null +++ b/02-serverless-api/test/MinioCustomizer.java @@ -0,0 +1,36 @@ +// camel-k: language=java +package test; + +import org.apache.camel.BindToRegistry; +import org.apache.camel.PropertyInject; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; + +public class MinioCustomizer { + + @BindToRegistry + public static AmazonS3 minioClient( + @PropertyInject("minio.endpoint") String endpointAddress, + @PropertyInject("minio.access-key") String accessKey, + @PropertyInject("minio.secret-key") String secretKey) { + + AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration(endpointAddress, "US_EAST_1"); + AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); + AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(credentials); + + return AmazonS3ClientBuilder + .standard() + .withEndpointConfiguration(endpoint) + .withCredentials(credentialsProvider) + .withPathStyleAccessEnabled(true) + .build(); + + } + +} diff --git a/02-serverless-api/test/crud.feature b/02-serverless-api/test/crud.feature new file mode 100644 index 0000000..ebcea50 --- /dev/null +++ b/02-serverless-api/test/crud.feature @@ -0,0 +1,65 @@ +Feature: the API allows CRUD operations on a S3 bucket + + + Background: + Given integration api is running + Given URL: http://api + + + Scenario: LIST objects + When send GET / + Then verify HTTP response header Content-Type="application/json" + And receive HTTP 200 OK + + + Scenario: SAVE object + Given variable objectName is "citrus:randomString(10)" + Given variable sampleText is "This is a sample text" + Given HTTP request header Content-Type is "application/octet-stream" + Given HTTP request body + """ + ${sampleText} + """ + When send PUT /${objectName} + Then receive HTTP 200 OK + Then verify HTTP response body + """ + ${sampleText} + """ + + + Scenario: GET object + Given variable objectName is "citrus:randomString(10)" + Given variable sampleText is "This is another sample text" + Given HTTP request body + """ + ${sampleText} + """ + Given HTTP request header Content-Type is "application/octet-stream" + Given send PUT /${objectName} + Given receive HTTP 200 OK + When send GET /${objectName} + Then receive HTTP 200 OK + Then verify HTTP response body + """ + ${sampleText} + """ + + + Scenario: DELETE object + Given variable objectName is "citrus:randomString(10)" + Given variable sampleText is "This is yet another sample text" + Given HTTP request body + """ + ${sampleText} + """ + Given HTTP request header Content-Type is "application/octet-stream" + Given send PUT /${objectName} + Given receive HTTP 200 OK + When send DELETE /${objectName} + Then receive HTTP 204 OK + + + Scenario: expose OpenAPI + When send GET /openapi.json + Then receive HTTP 200 OK diff --git a/02-serverless-api/test/minio.properties b/02-serverless-api/test/minio.properties new file mode 100644 index 0000000..9d15b40 --- /dev/null +++ b/02-serverless-api/test/minio.properties @@ -0,0 +1,15 @@ +# S3 Configuration + +# This configuration should not be kept together with the source code in production. + +# Bucket (referenced in the routes) +api.bucket=camel-k + +# Minio information injected into the MinioCustomizer +minio.endpoint=http://minio:9000 +minio.access-key=minio +minio.secret-key=minio123 + + +# General configuration +camel.context.rest-configuration.api-context-path=/openapi.json diff --git a/02-serverless-api/test/minio.yaml b/02-serverless-api/test/minio.yaml new file mode 100644 index 0000000..cd5f52d --- /dev/null +++ b/02-serverless-api/test/minio.yaml @@ -0,0 +1,71 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: minio +spec: + selector: + matchLabels: + app: minio + strategy: + type: Recreate + template: + metadata: + labels: + app: minio + spec: + volumes: + - name: data + persistentVolumeClaim: + claimName: minio-pv-claim + containers: + - name: minio + volumeMounts: + - name: data + mountPath: "/data" + image: minio/minio + args: + - server + - /data + env: + - name: MINIO_ACCESS_KEY + value: minio + - name: MINIO_SECRET_KEY + value: minio123 + ports: + - containerPort: 9000 + readinessProbe: + httpGet: + path: /minio/health/ready + port: 9000 + initialDelaySeconds: 10 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /minio/health/live + port: 9000 + initialDelaySeconds: 120 + periodSeconds: 20 +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: minio-pv-claim +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: minio +spec: + type: LoadBalancer + ports: + - port: 9000 + targetPort: 9000 + protocol: TCP + selector: + app: minio diff --git a/02-serverless-api/test/yaks-config.yaml b/02-serverless-api/test/yaks-config.yaml new file mode 100644 index 0000000..3b8e366 --- /dev/null +++ b/02-serverless-api/test/yaks-config.yaml @@ -0,0 +1,14 @@ +config: + namespace: + temporary: true +pre: +- name: minio installation + run: | + kubectl apply -f minio.yaml -n ${YAKS_NAMESPACE} + kubectl wait pod -l app=minio --for condition=Ready -n ${YAKS_NAMESPACE} --timeout=5m + +- name: integration + run: | + kamel install -w -n ${YAKS_NAMESPACE} + + kamel run --name api MinioCustomizer.java ../API.java --property-file minio.properties --open-api ../openapi.yaml -d camel-openapi-java -t 3scale.enabled=true -t 3scale.description-path=/openapi.json --profile OpenShift -w -n ${YAKS_NAMESPACE} diff --git a/README.md b/README.md index bf58d39..f1fbdf6 100644 --- a/README.md +++ b/README.md @@ -47,3 +47,4 @@ Most examples provide a `readme.didact.md` file instead of the standard readme f This is the current list of examples: - [01 Basic](./01-basic): Getting started with Camel K by learning the most important features that you should know before trying to develop more complex examples. +- [02 Serverless API](./02-serverless-api): Learn how to design an API that manages files in a remote storage location and leverages *Knative* Serving to scale automatically (even to zero instances) based on the current load.
