diff --git a/.gitignore b/.gitignore index 8626633..9fc2499 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ target/ *.txt node_modules/ local-docs/ -package-lock.json \ No newline at end of file +package-lock.json +.vscode diff --git a/README.adoc b/README.adoc index b4d61a9..a91fc61 100644 --- a/README.adoc +++ b/README.adoc @@ -1,3 +1 @@ -// Replace with the name of your repository, and replace with the title of the tutorial. -// For guidance on using this template, see .github/CONTRIBUTING.adoc -This repository hosts the documentation and code samples for the link:https://docs.hazelcast.com/tutorials/[ tutorial]. +This repository hosts the documentation and code samples for the link:https://docs.hazelcast.com/tutorials/hazelcast-platform-operator-user-code-namespace[hazelcast-platform-operator-user-code-namespace tutorial]. diff --git a/docs/modules/ROOT/examples/operator-user-code-namespace/hazelcast.yaml b/docs/modules/ROOT/examples/operator-user-code-namespace/hazelcast.yaml new file mode 100644 index 0000000..e37d759 --- /dev/null +++ b/docs/modules/ROOT/examples/operator-user-code-namespace/hazelcast.yaml @@ -0,0 +1,10 @@ +apiVersion: hazelcast.com/v1alpha1 +kind: Hazelcast +metadata: + name: hazelcast +spec: + clusterSize: 1 + repository: "docker.io/hazelcast/hazelcast-enterprise" + version: "5.4.0" + licenseKeySecretName: hazelcast-license-key + userCodeNamespaces: {} diff --git a/docs/modules/ROOT/examples/operator-user-code-namespace/map.yaml b/docs/modules/ROOT/examples/operator-user-code-namespace/map.yaml new file mode 100644 index 0000000..fc7e379 --- /dev/null +++ b/docs/modules/ROOT/examples/operator-user-code-namespace/map.yaml @@ -0,0 +1,9 @@ +apiVersion: hazelcast.com/v1alpha1 +kind: Map +metadata: + name: my-map +spec: + hazelcastResourceName: hazelcast + userCodeNamespace: my-ucn + entryListeners: + - className: com.hazelcast.tutorial.SimpleEntryListener diff --git a/docs/modules/ROOT/examples/operator-user-code-namespace/ucn.yaml b/docs/modules/ROOT/examples/operator-user-code-namespace/ucn.yaml new file mode 100644 index 0000000..c70c564 --- /dev/null +++ b/docs/modules/ROOT/examples/operator-user-code-namespace/ucn.yaml @@ -0,0 +1,9 @@ +apiVersion: hazelcast.com/v1alpha1 +kind: UserCodeNamespace +metadata: + name: my-ucn +spec: + hazelcastResourceName: hazelcast + bucketConfig: + secretName: + bucketURI: diff --git a/docs/modules/ROOT/pages/hazelcast-platform-operator-user-code-namespace.adoc b/docs/modules/ROOT/pages/hazelcast-platform-operator-user-code-namespace.adoc new file mode 100644 index 0000000..150f8f9 --- /dev/null +++ b/docs/modules/ROOT/pages/hazelcast-platform-operator-user-code-namespace.adoc @@ -0,0 +1,270 @@ += Deploying Custom Classes With the User Code Namespace +:page-layout: tutorial +:page-product: operator +:page-categories: Cloud Native +:page-lang: java +:page-enterprise: true +:page-est-time: 15 mins +:github-directory: https://github.com/hazelcast-guides/hazelcast-platform-operator-user-code-namespace +:description: Learn how to deploy custom classes with the User Code Namespace + +{description} + +== Context + +In this tutorial, you'll do the following: + +- Deploy Hazelcast with userCodeNamespaces enabled. + +- Create a custom EntryListener class and package it into a JAR. + +- Upload the JAR file to cloud storage. + +- Apply a UserCodeNamespace resource, referencing the JAR in storage. + +- Create a Map resource with the EntryListener, setting userCodeNamespaces the same as the UserCodeNamespace object. + +== Before you Begin + +You need the following: + +* Running https://kubernetes.io/[Kubernetes] cluster +* Kubernetes command-line tool, https://kubernetes.io/docs/tasks/tools/#kubectl[kubectl] +* Maven command-line tool, https://maven.apache.org/download.cgi[mvn] +* Deployed xref:operator:ROOT:index.adoc[Hazelcast Platform Operator version 5.12 or above] +* Blob storage and access credentials on one of the following cloud providers: https://aws.amazon.com/s3/[AWS], https://cloud.google.com/storage/[GCP], https://azure.microsoft.com/en-us/services/storage/blobs/[Azure] + +== Step 1. Start the Hazelcast Cluster + +. Create a license secret ++ +Create a secret with your link:http://trialrequest.hazelcast.com/[Hazelcast Enterprise License]. ++ +[source, shell] +---- +kubectl create secret generic hazelcast-license-key --from-literal=license-key= +---- + +. Create the Hazelcast Cluster ++ +Run the following command to create the Hazelcast cluster with Persistence enabled using External type. ++ +[source, shell] +---- +kubectl apply -f - < +---- +-- + +GCS:: ++ +-- +[source,bash] +---- +gsutil cp simple-entry-listener/target/simple-entry-listener-1.0-SNAPSHOT.jar gs:// +---- +-- + +ABS:: ++ +-- +[source,bash] +---- +az storage blob upload --account-name --container-name --file simple-entry-listener/target/simple-entry-listener-1.0-SNAPSHOT.jar +---- +-- + +==== + +. Create a secret for your cloud storage by running one of the following commands. Remember to replace the placeholder values. + ++ +[tabs] +==== + +AWS:: ++ +-- +[source,bash] +---- +kubectl create secret generic --from-literal=region= \ + --from-literal=access-key-id= \ + --from-literal=secret-access-key= +---- +-- + +GCP:: ++ +-- +[source,bash] +---- +kubectl create secret generic --from-file=google-credentials-path= +---- +-- + +Azure:: ++ +-- +[source,bash] +---- +kubectl create secret generic \ + --from-literal=storage-account= \ + --from-literal=storage-key= +---- +-- + +==== + +== Step 3. Apply the UserCodeNamespace resource + +. Apply the UserCodeNamespace resource ++ +Run the following command to create the UserCodeDeployment, referencing to the bucket where the EntryLister JAR is located. ++ +[source, shell] +---- +kubectl apply -f - < +$ kubectl delete secret hazelcast-license-key +$ kubectl delete hazelcast hazelcast +---- + +== See Also + +- xref:operator:ROOT:user-code-namespaces.adoc[] diff --git a/docs/modules/ROOT/pages/rename-me.adoc b/docs/modules/ROOT/pages/rename-me.adoc deleted file mode 100644 index 35e4e10..0000000 --- a/docs/modules/ROOT/pages/rename-me.adoc +++ /dev/null @@ -1,57 +0,0 @@ -//// -Make sure to rename this file to the name of your repository and add the filename to the README. This filename must not conflict with any existing tutorials. -//// - -// Describe the title of your article by replacing 'Tutorial template' with the page name you want to publish. -= Tutorial template -// Add required variables -:page-layout: tutorial -:page-product: // Required: Define the product filter for this tutorial. Add one of the following: platform, imdg, cloud, operator -:page-categories: // Optional: Define the categories for this tutorial. Check the current categories on the tutorials homepage (https://docs.hazelcast.com/tutorials/). Add one or more of the existing categories or add new ones as a comma-separated list. Make sure that you use title case for all categories. -:page-lang: java // Optional: Define what Hazelcast client languages are supported by this tutorial. Leave blank or add one or more of: java, go, python, cplus, node, csharp. -:page-enterprise: // Required: Define whether this tutorial requires an Enterprise license (true or blank) -:page-est-time: // Required: Define the estimated number of time required to complete the tutorial in minutes. For example, 10 mins -:description: // Required: Summarize what this tutorial is about in a sentence or two. What you put here is reused as the tutorial's first paragraph and included in HTML description tags. Start the sentence with an action verb such as 'Deploy' or 'Connect'. - -{description} - -// Give some context about the use case for this tutorial. What will the reader learn? -== Context - -// Optional: What does the reader need before starting this tutorial? Think about tools or knowledge. Delete this section if your readers can dive straight into the lesson without requiring any prerequisite knowledge. -== Before you Begin - -Before starting this tutorial, make sure that you meet the following prerequisites: - -* Prerequisite one -* Prerequisite two -* etc - -== Step 1. - -//// -Introduce what your audience will learn in each step, then continue to write the steps in the tutorial. -You can choose one of these approaches to write your tutorial part: - -* In a narrative style if your parts are short or you are using screenshots to do most of the talking. -* In a "Goal > Steps > Outcome" structure to build a predictable flow in all your tutorial parts. - -Whatever option you choose when designing your tutorial should be carried through in subsequent parts. -//// - -== Step 2. - -//// -Continue the design approach you chose in the previous part and continue it through to the end of the tutorial. -//// - -== Summary - -//// -Summarise what knowledge the reader has gained by completing the tutorial, including a summary of each step's goals (this is a good way to validate whether your tutorial has covered all you need it to.) -//// - - -== See Also - -// Optionally, add some links to resources, such as other related guides. diff --git a/simple-entry-listener/pom.xml b/simple-entry-listener/pom.xml new file mode 100644 index 0000000..5fba08d --- /dev/null +++ b/simple-entry-listener/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + + com.hazelcast.tutorial + simple-entry-listener + jar + + 1.0-SNAPSHOT + simple-entry-listener + + + 17 + 17 + + + + + + com.hazelcast + hazelcast + 5.4.0 + + + + \ No newline at end of file diff --git a/simple-entry-listener/src/main/java/com/hazelcast/tutorial/SimpleEntryListener.java b/simple-entry-listener/src/main/java/com/hazelcast/tutorial/SimpleEntryListener.java new file mode 100644 index 0000000..eec2efd --- /dev/null +++ b/simple-entry-listener/src/main/java/com/hazelcast/tutorial/SimpleEntryListener.java @@ -0,0 +1,28 @@ +package com.hazelcast.tutorial; + +import com.hazelcast.core.EntryEvent; +import com.hazelcast.core.HazelcastJsonValue; +import com.hazelcast.map.listener.EntryAddedListener; +import com.hazelcast.map.listener.EntryRemovedListener; +import com.hazelcast.map.listener.EntryUpdatedListener; + +public class SimpleEntryListener implements EntryAddedListener, + EntryUpdatedListener, + EntryRemovedListener { + + @Override + public void entryAdded(EntryEvent event) { + System.out.println("Entry Added:" + event); + } + + @Override + public void entryRemoved(EntryEvent event) { + System.out.println("Entry Removed:" + event); + } + + @Override + public void entryUpdated(EntryEvent event) { + System.out.println("Entry Updated:" + event); + } + +}