Skip to content

Commit

Permalink
Add the Coherence CLI to the Operator image (#606)
Browse files Browse the repository at this point in the history
  • Loading branch information
thegridman authored Jul 17, 2023
1 parent 63917a1 commit ab02646
Show file tree
Hide file tree
Showing 9 changed files with 293 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ LABEL "com.oracle.coherence.version"="$version"
ENV COHERENCE_IMAGE=$coherence_image \
OPERATOR_IMAGE=$operator_image

COPY bin/linux/$target/runner /files/runner
COPY bin/linux/$target/* /files/
COPY java/coherence-operator/target/docker/lib/*.jar /files/lib/
COPY java/coherence-operator/target/docker/logging/logging.properties /files/logging/logging.properties

Expand Down
33 changes: 28 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ TEST_ASSET_KUBECTL ?= $(shell which kubectl)
override BUILD_OUTPUT := $(CURRDIR)/build/_output
override BUILD_ASSETS := pkg/data/assets
override BUILD_BIN := $(CURRDIR)/bin
override BUILD_BIN_AMD64 := $(BUILD_BIN)/linux/amd64
override BUILD_BIN_ARM64 := $(BUILD_BIN)/linux/arm64
override BUILD_DEPLOY := $(BUILD_OUTPUT)/config
override BUILD_HELM := $(BUILD_OUTPUT)/helm-charts
override BUILD_MANIFESTS := $(BUILD_OUTPUT)/manifests
Expand Down Expand Up @@ -429,7 +431,7 @@ clean-tools: ## Cleans the locally downloaded build tools (i.e. need a new tool
.PHONY: build-operator
build-operator: $(BUILD_TARGETS)/build-operator ## Build the Coherence Operator image

$(BUILD_TARGETS)/build-operator: $(BUILD_BIN)/runner build-mvn
$(BUILD_TARGETS)/build-operator: $(BUILD_BIN)/runner build-mvn coherence-cli
docker build --no-cache --build-arg version=$(VERSION) \
--build-arg BASE_IMAGE=$(OPERATOR_BASE_IMAGE) \
--build-arg coherence_image=$(COHERENCE_IMAGE) \
Expand Down Expand Up @@ -527,10 +529,10 @@ build-runner: $(BUILD_BIN)/runner ## Build the Coherence Operator runner binary

$(BUILD_BIN)/runner: $(BUILD_PROPS) $(GOS) $(BUILD_TARGETS)/generate $(BUILD_TARGETS)/manifests
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -trimpath -ldflags "$(LDFLAGS)" -o $(BUILD_BIN)/runner ./runner
mkdir -p $(BUILD_BIN)/linux/amd64 || true
cp -f $(BUILD_BIN)/runner $(BUILD_BIN)/linux/amd64/runner
mkdir -p $(BUILD_BIN)/linux/arm64 || true
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GO111MODULE=on go build -trimpath -ldflags "$(LDFLAGS)" -a -o $(BUILD_BIN)/linux/arm64/runner ./runner
mkdir -p $(BUILD_BIN_AMD64) || true
cp -f $(BUILD_BIN)/runner $(BUILD_BIN_AMD64)/runner
mkdir -p $(BUILD_BIN_ARM64)/linux || true
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GO111MODULE=on go build -trimpath -ldflags "$(LDFLAGS)" -a -o $(BUILD_BIN_ARM64)/runner ./runner

# ----------------------------------------------------------------------------------------------------------------------
# Build the Java artifacts
Expand Down Expand Up @@ -683,6 +685,7 @@ copyright: ## Check copyright headers
-X examples/helm/chart/templates/NOTES.txt \
-X .factories \
-X hack/copyright.txt \
-X hack/install-cli.sh \
-X hack/intellij-codestyle.xml \
-X hack/istio- \
-X hack/sdk/ \
Expand Down Expand Up @@ -1839,6 +1842,26 @@ KUSTOMIZE = $(TOOLS_BIN)/kustomize
kustomize: ## Download kustomize locally if necessary.
test -s $(TOOLS_BIN)/kustomize || { curl -Ss $(KUSTOMIZE_INSTALL_SCRIPT) --header $(GH_AUTH) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(TOOLS_BIN); }

# ----------------------------------------------------------------------------------------------------------------------
# find or download the Coherence CLI
# ----------------------------------------------------------------------------------------------------------------------
.PHONY: coherence-cli
coherence-cli: $(BUILD_BIN_AMD64)/cohctl $(BUILD_BIN_ARM64)/cohctl ## Download the Coherence CLI locally if necessary.

$(BUILD_BIN_AMD64)/cohctl: export COHCTL_HOME=$(BUILD_BIN_AMD64)
$(BUILD_BIN_AMD64)/cohctl: export OS=Linux
$(BUILD_BIN_AMD64)/cohctl: export ARCH=x86_64
$(BUILD_BIN_AMD64)/cohctl:
./hack/install-cli.sh
chmod +x $(BUILD_BIN_AMD64)/cohctl

$(BUILD_BIN_ARM64)/cohctl: export COHCTL_HOME=$(BUILD_BIN_ARM64)
$(BUILD_BIN_ARM64)/cohctl: export OS=Linux
$(BUILD_BIN_ARM64)/cohctl: export ARCH=arm64
$(BUILD_BIN_ARM64)/cohctl:
./hack/install-cli.sh
chmod +x $(BUILD_BIN_ARM64)/cohctl

# ----------------------------------------------------------------------------------------------------------------------
# find or download gotestsum
# ----------------------------------------------------------------------------------------------------------------------
Expand Down
9 changes: 8 additions & 1 deletion docs/management/010_overview.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////

Copyright (c) 2020, Oracle and/or its affiliates.
Copyright (c) 2020, 2023, Oracle and/or its affiliates.
Licensed under the Universal Permissive License v 1.0 as shown at
http://oss.oracle.com/licenses/upl.

Expand All @@ -22,6 +22,13 @@ in a cluster deployed in Kubernetes.
Coherence Management over REST feature
--
[CARD]
.The Coherence CLI
[link=docs/management/025_coherence_cli.adoc]
--
Using the Coherence CLI in Pods
--
[CARD]
.VisualVM
[link=docs/management/030_visualvm.adoc]
Expand Down
96 changes: 96 additions & 0 deletions docs/management/025_coherence_cli.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
///////////////////////////////////////////////////////////////////////////////

Copyright (c) 2023, Oracle and/or its affiliates.
Licensed under the Universal Permissive License v 1.0 as shown at
http://oss.oracle.com/licenses/upl.

///////////////////////////////////////////////////////////////////////////////
= The Coherence CLI
== The Coherence CLI
If Coherence Management over REST is enabled, it is possible to use the
https://github.com/oracle/coherence-cli[Coherence CLI]
to access management information. The Operator enables Coherence Management over REST by default, so unless it
has specifically been disabled, the CLI can be used.
See the https://oracle.github.io/coherence-cli/docs/latest/#/docs/about/01_overview[Coherence CLI Documentation]
for more information on how to use the CLI.
The Coherence CLI is automatically added to Coherence Pods by the Operator, so it is available as an executable
that can be run using `kubectl exec`.
At start-up of a Coherence container a default Coherence CLI configuration is created so that the CLI
knows about the local cluster member.
=== Using the CLI in Pods
The Operator installs the CLI at the location `/coherence-operator/utils/cohctl`.
Most official Coherence images are distroless images so they do not have a shell that can be used to create a session and execute commands. Each `cohctl` command will need to be executed as a separate `kubectl exec` command.
Once a Pod is running is it simple to use the CLI.
For example, the yaml below will create a simple three member cluster.
[source]
.minimal.yaml
----
apiVersion: coherence.oracle.com/v1
kind: Coherence
metadata:
name: storage
spec:
replicas: 3
----
The cluster name is `storage` and there will be three Pods created, `storage-0`, `storage-1` and `storage-2`.
To list the services running in the `storage-0` Pod the following command can be run:
[source,bash]
----
kubectl exec storage-0 -c coherence -- /coherence-operator/utils/cohctl get services
----
The `-c coherence` option tells `kubectl` to exec the command in the `coherence` container.
By default this is the only container that will be running in the Pod, so the option could be omitted.
If the option is omitted, `kubectl` will display a warning to say it assumes you mean the `coherence` container.
Everything after the `--` is the command to run in the Pod. In this case we execute:
[source,bash]
----
/coherence-operator/utils/cohctl get services
----
which runs the Coherence CLI binary at `/coherence-operator/utils/cohctl` with the command `get services`.
The output displayed by the command will look something like this:
[source,bash]
----
Using cluster connection 'default' from current context.
SERVICE NAME TYPE MEMBERS STATUS HA STORAGE PARTITIONS
"$GRPC:GrpcProxy" Proxy 3 n/a -1 -1
"$SYS:Concurrent" DistributedCache 3 NODE-SAFE 3 257
"$SYS:ConcurrentProxy" Proxy 3 n/a -1 -1
"$SYS:Config" DistributedCache 3 NODE-SAFE 3 257
"$SYS:HealthHttpProxy" Proxy 3 n/a -1 -1
"$SYS:SystemProxy" Proxy 3 n/a -1 -1
ManagementHttpProxy Proxy 3 n/a -1 -1
MetricsHttpProxy Proxy 3 n/a -1 -1
PartitionedCache DistributedCache 3 NODE-SAFE 3 257
PartitionedTopic PagedTopic 3 NODE-SAFE 3 257
Proxy Proxy 3 n/a -1 -1
----
The exact output will vary depending on the version of Coherence and the configurations being used.
More CLI commands can be run by changing the CLI commands specified after `/coherence-operator/utils/cohctl`.
For example, to list all the members of the cluster:
[source,bash]
----
kubectl exec storage-0 -c coherence -- /coherence-operator/utils/cohctl get members
----
43 changes: 43 additions & 0 deletions hack/install-cli.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/bash
#
# Copyright (c) 2019, 2023, Oracle and/or its affiliates.
# Licensed under the Universal Permissive License v 1.0 as shown at
# http://oss.oracle.com/licenses/upl.
#
VERSION=$(curl -s https://oracle.github.io/coherence-cli/stable.txt)

function set_arch() {
if [ "$ARCH" == "x86_64" ] ; then
ARCH="amd64"
elif [ "$ARCH" == "aarch64" -o "$ARCH" == "arm64" ] ; then
ARCH="arm64"
else
echo "Unsupported architecture: $ARCH"
exit 1
fi
}

function installed() {
echo "Installed cohctl into ${COHCTL_HOME}"
}

echo "Installing Coherence CLI ${VERSION} for ${OS}/${ARCH} into ${COHCTL_HOME} ..."

if [ "$OS" == "Darwin" ]; then
set_arch
TEMP=`mktemp -d`
PKG="Oracle-Coherence-CLI-${VERSION}-darwin-${ARCH}.pkg"
DEST=${TEMP}/${PKG}
echo "Downloading and opening ${DEST}"
URL=https://github.com/oracle/coherence-cli/releases/download/${VERSION}/${PKG}
curl -sLo ${DEST} $URL && open ${DEST} && installed
elif [ "$OS" == "Linux" ]; then
set_arch
TEMP=`mktemp -d`
URL=https://github.com/oracle/coherence-cli/releases/download/${VERSION}/cohctl-${VERSION}-linux-${ARCH}
curl -sLo ${TEMP}/cohctl $URL && chmod u+x ${TEMP}/cohctl
mv ${TEMP}/cohctl ${COHCTL_HOME} && installed
else
echo "For all other platforms, please see: https://github.com/oracle/coherence-cli/releases"
exit 1
fi
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
/*
* Copyright (c) 2019, 2022, Oracle and/or its affiliates.
* Copyright (c) 2019, 2023, Oracle and/or its affiliates.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/

package com.oracle.coherence.k8s;

import java.io.File;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.concurrent.CompletableFuture;

import com.tangosol.coherence.config.Config;
import com.tangosol.net.CacheFactory;
import com.tangosol.net.Cluster;
import com.tangosol.net.Coherence;
import com.tangosol.net.DefaultCacheServer;
import com.tangosol.net.Member;

/**
* A main class that is used to run some initialisation code before
Expand Down Expand Up @@ -42,6 +49,7 @@ else if (DEFAULT_MAIN.equals(args[0])) {
}

init();
CompletableFuture.runAsync(Main::initCohCtl);

String sMainClass = args[0];
String[] asArgsReal = new String[args.length - 1];
Expand Down Expand Up @@ -75,4 +83,57 @@ private static String getMainClass() {
return DefaultCacheServer.class.getCanonicalName();
}
}

private static void initCohCtl() {
try {
Cluster cluster = CacheFactory.getCluster();
Member member = cluster.getLocalMember();
String clusterName = member.getClusterName();
String port = Config.getProperty("coherence.management.http.port", "30000");
String provider = Config.getProperty("coherence.management.http.provider");
String defaultProtocol = provider == null || provider.isEmpty() ? "http" : "https";
String protocol = Config.getProperty("coherence.operator.cli.protocol", defaultProtocol);
String home = System.getProperty("user.home");
String connectionType = "http";

File cohctlHome = new File(home + File.separator + ".cohctl");
File configFile = new File(cohctlHome, "cohctl.yaml");

if (!configFile.exists()) {
System.out.println("CoherenceOperator: creating default cohctl config at " + configFile.getAbsolutePath());
if (!cohctlHome.exists()) {
cohctlHome.mkdirs();
}
try (PrintWriter out = new PrintWriter(configFile)) {
out.println("clusters:");
out.println(" - name: default");
out.println(" discoverytype: manual");
out.println(" connectiontype: " + connectionType);
out.println(" connectionurl: " + protocol + "://127.0.0.1:" + port + "/management/coherence/cluster");
out.println(" nameservicediscovery: \"\"");
out.println(" clusterversion: \"" + CacheFactory.VERSION + "\"");
out.println(" clustername: \"" + clusterName + "\"");
out.println(" clustertype: Standalone");
out.println(" manuallycreated: false");
out.println(" baseclasspath: \"\"");
out.println(" additionalclasspath: \"\"");
out.println(" arguments: \"\"");
out.println(" managementport: 0");
out.println(" persistencemode: \"\"");
out.println(" loggingdestination: \"\"");
out.println(" managementavailable: false");
out.println("color: \"on\"");
out.println("currentcontext: default");
out.println("debug: false");
out.println("defaultbytesformat: m");
out.println("ignoreinvalidcerts: false");
out.println("requesttimeout: 30");
}
}
}
catch (Exception e) {
System.err.println("Coherence Operator: Failed to create default cohctl config");
e.printStackTrace();
}
}
}
11 changes: 10 additions & 1 deletion pkg/runner/cmd_initialise.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates.
* Copyright (c) 2021, 2023, Oracle and/or its affiliates.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
Expand Down Expand Up @@ -151,6 +151,15 @@ func initialiseWithEnv(cmd *cobra.Command, getEnv EnvFunction) (bool, error) {
}
}

cohctl := filesDir + pathSep + "cohctl"
if _, err := os.Stat(cohctl); err == nil {
fmt.Println("Copying cohctl utility")
err = utils.CopyFile(cohctl, utilDir+pathSep+"cohctl")
if err != nil {
return false, err
}
}

var dirNames []string

_, err = os.Stat(persistenceDir)
Expand Down
35 changes: 35 additions & 0 deletions test/e2e/local/cli_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2019, 2023, Oracle and/or its affiliates.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/

package local

import (
. "github.com/onsi/gomega"
coh "github.com/oracle/coherence-operator/api/v1"
"github.com/oracle/coherence-operator/test/e2e/helper"
"os/exec"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"testing"
)

// Test that the Coherence CLI can be executed in a Pod
func TestCoherenceCLI(t *testing.T) {
// Make sure we defer clean-up when we're done!!
testContext.CleanupAfterTest(t)
g := NewWithT(t)

deployments, _ := helper.AssertDeployments(testContext, t, "deployment-cli.yaml")

data, ok := deployments["storage"]
g.Expect(ok).To(BeTrue(), "did not find expected 'storage' deployment")

hasFinalizer := controllerutil.ContainsFinalizer(&data, coh.CoherenceFinalizer)
g.Expect(hasFinalizer).To(BeTrue())

_, err := exec.Command("kubectl", "-n", data.Namespace, "exec", "storage-0",
"-c", "coherence", "--", "/coherence-operator/utils/cohctl", "get", "members").CombinedOutput()
g.Expect(err).NotTo(HaveOccurred())
}
10 changes: 10 additions & 0 deletions test/e2e/local/deployment-cli.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: coherence.oracle.com/v1
kind: Coherence
metadata:
name: storage
spec:
env:
- name: COH_SKIP_SITE
value: "true"


0 comments on commit ab02646

Please sign in to comment.