From f90addf32e2e7ca4298f2aa7fc0e03c0372f23b0 Mon Sep 17 00:00:00 2001 From: Jonathan Knight Date: Mon, 17 Feb 2025 13:18:33 +0300 Subject: [PATCH 01/11] Fix using the Coherence console via kubectl exec --- pkg/operator/operator.go | 10 ++++++++ pkg/runner/cmd_console.go | 15 +++++++----- pkg/runner/cmd_jshell.go | 16 ++++++++----- pkg/runner/cmd_query_plus.go | 16 ++++++++----- pkg/runner/cmd_sleep.go | 13 ++++++++--- pkg/runner/run_details.go | 1 + pkg/runner/runner.go | 44 +++++++++++++++++++++++++++++++++--- 7 files changed, 91 insertions(+), 24 deletions(-) diff --git a/pkg/operator/operator.go b/pkg/operator/operator.go index a20de6d09..7f8fdecff 100644 --- a/pkg/operator/operator.go +++ b/pkg/operator/operator.go @@ -77,6 +77,8 @@ const ( FlagWebhookCertDir = "webhook-cert-dir" FlagWebhookSecret = "webhook-secret" FlagWebhookService = "webhook-service" + FlagEnvVar = "env" + FlagJvmArg = "jvm" // EnvVarWatchNamespace is the environment variable to use to set the watch namespace(s) EnvVarWatchNamespace = "WATCH_NAMESPACE" @@ -476,6 +478,14 @@ func GetGlobalLabels(v *viper.Viper) (map[string]string, error) { return stringSliceToMap(args, FlagGlobalLabel) } +func GetExtraEnvVars() []string { + return GetViper().GetStringSlice(FlagEnvVar) +} + +func GetExtraJvmArgs() []string { + return GetViper().GetStringSlice(FlagJvmArg) +} + func stringSliceToMap(args []string, flag string) (map[string]string, error) { var m map[string]string if args != nil { diff --git a/pkg/runner/cmd_console.go b/pkg/runner/cmd_console.go index 1ae7827bc..390e6be28 100644 --- a/pkg/runner/cmd_console.go +++ b/pkg/runner/cmd_console.go @@ -20,16 +20,20 @@ const ( // consoleCommand creates the cobra sub-command to run a Coherence CacheFactory console. func consoleCommand(v *viper.Viper) *cobra.Command { - return &cobra.Command{ + cmd := &cobra.Command{ Use: CommandConsole, Short: "Start a Coherence interactive console", Long: "Starts a Coherence interactive console", RunE: func(cmd *cobra.Command, args []string) error { - return run(cmd, func(details *RunDetails, _ *cobra.Command) { + return run(cmd, func(details *RunDetails, cmd *cobra.Command) { console(details, args, v) }) }, } + addEnvVarFlag(cmd) + addJvmArgFlag(cmd) + setupFlags(cmd, v) + return cmd } // Configure the runner to run a Coherence CacheFactory console @@ -45,10 +49,9 @@ func console(details *RunDetails, args []string, v *viper.Viper) { } details.Command = CommandConsole details.addArg("-Dcoherence.distributed.localstorage=false") + details.addArg("-Dcoherence.localport.adjust=true") + details.addArg("-Dcoherence.management.http.enabled=false") + details.addArg("-Dcoherence.metrics.http.enabled=false") details.setenv(v1.EnvVarCohRole, "console") - details.unsetenv(v1.EnvVarJvmMemoryHeap) - details.unsetenv(v1.EnvVarCoherenceLocalPortAdjust) - details.unsetenv(v1.EnvVarCohMgmtPrefix + v1.EnvVarCohEnabledSuffix) - details.unsetenv(v1.EnvVarCohMetricsPrefix + v1.EnvVarCohEnabledSuffix) details.MainArgs = args } diff --git a/pkg/runner/cmd_jshell.go b/pkg/runner/cmd_jshell.go index 9c32b5560..83f6e5483 100644 --- a/pkg/runner/cmd_jshell.go +++ b/pkg/runner/cmd_jshell.go @@ -9,6 +9,7 @@ package runner import ( v1 "github.com/oracle/coherence-operator/api/v1" "github.com/spf13/cobra" + "github.com/spf13/viper" "os" ) @@ -18,8 +19,8 @@ const ( ) // queryPlusCommand creates the corba "jshell" sub-command -func jShellCommand() *cobra.Command { - return &cobra.Command{ +func jShellCommand(v *viper.Viper) *cobra.Command { + cmd := &cobra.Command{ Use: CommandJShell, Short: "Start a Coherence interactive JShell console", Long: "Starts a Coherence interactive JShell console", @@ -28,6 +29,10 @@ func jShellCommand() *cobra.Command { return run(cmd, jShell) }, } + addEnvVarFlag(cmd) + addJvmArgFlag(cmd) + setupFlags(cmd, v) + return cmd } // Configure the runner to run a Coherence JShell console @@ -39,9 +44,8 @@ func jShell(details *RunDetails, _ *cobra.Command) { details.MainArgs = os.Args[2:] } details.addArg("-Dcoherence.distributed.localstorage=false") + details.addArg("-Dcoherence.localport.adjust=true") + details.addArg("-Dcoherence.management.http.enabled=false") + details.addArg("-Dcoherence.metrics.http.enabled=false") details.setenv(v1.EnvVarCohRole, "jshell") - details.unsetenv(v1.EnvVarJvmMemoryHeap) - details.unsetenv(v1.EnvVarCoherenceLocalPortAdjust) - details.unsetenv(v1.EnvVarCohMgmtPrefix + v1.EnvVarCohEnabledSuffix) - details.unsetenv(v1.EnvVarCohMetricsPrefix + v1.EnvVarCohEnabledSuffix) } diff --git a/pkg/runner/cmd_query_plus.go b/pkg/runner/cmd_query_plus.go index 2efa8d6b4..e989326e1 100644 --- a/pkg/runner/cmd_query_plus.go +++ b/pkg/runner/cmd_query_plus.go @@ -9,6 +9,7 @@ package runner import ( v1 "github.com/oracle/coherence-operator/api/v1" "github.com/spf13/cobra" + "github.com/spf13/viper" "os" ) @@ -18,8 +19,8 @@ const ( ) // queryPlusCommand creates the corba "queryplus" sub-command -func queryPlusCommand() *cobra.Command { - return &cobra.Command{ +func queryPlusCommand(v *viper.Viper) *cobra.Command { + cmd := &cobra.Command{ Use: CommandQueryPlus, Short: "Start a Coherence interactive QueryPlus console", Long: "Starts a Coherence interactive QueryPlus console", @@ -28,6 +29,10 @@ func queryPlusCommand() *cobra.Command { return run(cmd, queryPlus) }, } + addEnvVarFlag(cmd) + addJvmArgFlag(cmd) + setupFlags(cmd, v) + return cmd } // Configure the runner to run a Coherence Query Plus console @@ -39,9 +44,8 @@ func queryPlus(details *RunDetails, _ *cobra.Command) { details.MainArgs = os.Args[2:] } details.addArg("-Dcoherence.distributed.localstorage=false") + details.addArg("-Dcoherence.localport.adjust=true") + details.addArg("-Dcoherence.management.http.enabled=false") + details.addArg("-Dcoherence.metrics.http.enabled=false") details.setenv(v1.EnvVarCohRole, "queryPlus") - details.unsetenv(v1.EnvVarJvmMemoryHeap) - details.unsetenv(v1.EnvVarCoherenceLocalPortAdjust) - details.unsetenv(v1.EnvVarCohMgmtPrefix + v1.EnvVarCohEnabledSuffix) - details.unsetenv(v1.EnvVarCohMetricsPrefix + v1.EnvVarCohEnabledSuffix) } diff --git a/pkg/runner/cmd_sleep.go b/pkg/runner/cmd_sleep.go index b5ced347e..32f6ca259 100644 --- a/pkg/runner/cmd_sleep.go +++ b/pkg/runner/cmd_sleep.go @@ -9,6 +9,7 @@ package runner import ( v1 "github.com/oracle/coherence-operator/api/v1" "github.com/spf13/cobra" + "github.com/spf13/viper" ) const ( @@ -17,8 +18,8 @@ const ( ) // queryPlusCommand creates the corba "sleep" sub-command -func sleepCommand() *cobra.Command { - return &cobra.Command{ +func sleepCommand(v *viper.Viper) *cobra.Command { + cmd := &cobra.Command{ Use: CommandSleep, Short: "Sleep for a number of seconds", Long: "Sleep for a number of seconds", @@ -29,6 +30,10 @@ func sleepCommand() *cobra.Command { }) }, } + addEnvVarFlag(cmd) + addJvmArgFlag(cmd) + setupFlags(cmd, v) + return cmd } func sleep(details *RunDetails, args []string) { @@ -38,6 +43,8 @@ func sleep(details *RunDetails, args []string) { details.MainArgs = args details.UseOperatorHealth = true details.addArg("-Dcoherence.distributed.localstorage=false") + details.addArg("-Dcoherence.localport.adjust=true") + details.addArg("-Dcoherence.management.http.enabled=false") + details.addArg("-Dcoherence.metrics.http.enabled=false") details.setenv(v1.EnvVarCohRole, "sleep") - details.unsetenv(v1.EnvVarJvmMemoryHeap) } diff --git a/pkg/runner/run_details.go b/pkg/runner/run_details.go index 7ed640725..ff45807d6 100644 --- a/pkg/runner/run_details.go +++ b/pkg/runner/run_details.go @@ -53,6 +53,7 @@ type RunDetails struct { MainClass string MainArgs []string BuildPacks *bool + ExtraEnv []string env *viper.Viper } diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 0a8da4101..24947be1e 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -125,14 +125,14 @@ func NewRootCommand(env map[string]string, v *viper.Viper) *cobra.Command { rootCmd.AddCommand(initCommand(env)) rootCmd.AddCommand(serverCommand()) rootCmd.AddCommand(consoleCommand(v)) - rootCmd.AddCommand(queryPlusCommand()) + rootCmd.AddCommand(queryPlusCommand(v)) rootCmd.AddCommand(statusCommand()) rootCmd.AddCommand(readyCommand()) rootCmd.AddCommand(nodeCommand()) rootCmd.AddCommand(operatorCommand(v)) rootCmd.AddCommand(networkTestCommand()) - rootCmd.AddCommand(jShellCommand()) - rootCmd.AddCommand(sleepCommand()) + rootCmd.AddCommand(jShellCommand(v)) + rootCmd.AddCommand(sleepCommand(v)) return rootCmd } @@ -600,6 +600,11 @@ func createCommand(details *RunDetails) (string, *exec.Cmd, error) { details.addArgs(strings.Split(jvmArgs, " ")...) } + extraJvmArgs := operator.GetExtraJvmArgs() + if extraJvmArgs != nil { + details.addArgs(extraJvmArgs...) + } + var cmd *exec.Cmd var app string switch { @@ -623,6 +628,11 @@ func createCommand(details *RunDetails) (string, *exec.Cmd, error) { cmd, err = createGraalCommand(details) } + extraEnv := operator.GetExtraEnvVars() + if cmd != nil && extraEnv != nil { + cmd.Env = append(cmd.Env, extraEnv...) + } + return app, cmd, err } @@ -1131,3 +1141,31 @@ func closeFile(f *os.File, log logr.Logger) { log.Error(err, "error closing file "+f.Name()) } } + +func addEnvVarFlag(cmd *cobra.Command) { + cmd.PersistentFlags().StringSlice( + operator.FlagEnvVar, + nil, + "Additional environment variables to pass to the process", + ) +} + +func addJvmArgFlag(cmd *cobra.Command) { + cmd.PersistentFlags().StringSlice( + operator.FlagJvmArg, + nil, + "AdditionalJVM args to pass to the process", + ) +} + +func setupFlags(cmd *cobra.Command, v *viper.Viper) { + // enable using dashed notation in flags and underscores in env + v.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) + + if err := v.BindPFlags(cmd.Flags()); err != nil { + setupLog.Error(err, "binding flags") + os.Exit(1) + } + + v.AutomaticEnv() +} From d196e0f8209bcc4d624e5df8bb524ed1d73369df Mon Sep 17 00:00:00 2001 From: Jonathan Knight Date: Thu, 20 Feb 2025 18:05:26 +0300 Subject: [PATCH 02/11] Fix code review failures --- pkg/operator/operator.go | 2 +- pkg/runner/run_details.go | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/pkg/operator/operator.go b/pkg/operator/operator.go index 7f8fdecff..3b693074b 100644 --- a/pkg/operator/operator.go +++ b/pkg/operator/operator.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. * Licensed under the Universal Permissive License v 1.0 as shown at * http://oss.oracle.com/licenses/upl. */ diff --git a/pkg/runner/run_details.go b/pkg/runner/run_details.go index ff45807d6..97c14b44d 100644 --- a/pkg/runner/run_details.go +++ b/pkg/runner/run_details.go @@ -199,13 +199,6 @@ func (in *RunDetails) setenv(key, value string) { in.env.Set(key, value) } -func (in *RunDetails) unsetenv(key string) { - if in.env == nil { - in.env = viper.New() - } - in.env.Set(key, nil) -} - func (in *RunDetails) isEnvTrue(name string) bool { value := in.Getenv(name) return strings.ToLower(value) == "true" From df77031aab5e3fcd7e5b6353030caf663f279838 Mon Sep 17 00:00:00 2001 From: Jonathan Knight Date: Thu, 20 Feb 2025 19:37:26 +0300 Subject: [PATCH 03/11] Manifest changes for OpenShift (#697) --- .github/workflows/compatibility-tests.yaml | 15 - .github/workflows/release.yml | 13 +- Dockerfile | 16 + Makefile | 387 +++++++++++------- PROJECT | 3 +- config/manager/manager.yaml | 22 + ...erence-operator.clusterserviceversion.yaml | 53 +-- .../coherence.oracle.com_v1_coherence.yaml | 2 +- hack/coherence-certification.sh | 2 +- hack/ensure-sdk.sh | 18 +- hack/k8s-certification.sh | 2 +- hack/preflight.yaml | 64 +++ hack/setup-podman.sh | 21 + helm-charts/coherence-operator/Chart.yaml | 3 +- .../templates/deployment.yaml | 17 +- java/operator-test-helidon/pom.xml | 2 +- java/operator-test-spring/pom.xml | 2 +- java/operator-test/pom.xml | 2 +- java/pom.xml | 2 +- 19 files changed, 439 insertions(+), 207 deletions(-) create mode 100644 hack/preflight.yaml create mode 100644 hack/setup-podman.sh diff --git a/.github/workflows/compatibility-tests.yaml b/.github/workflows/compatibility-tests.yaml index 6dc2fb87a..4a54890a4 100644 --- a/.github/workflows/compatibility-tests.yaml +++ b/.github/workflows/compatibility-tests.yaml @@ -48,9 +48,6 @@ jobs: - 3.3.0 - 3.2.11 - 3.2.10 - - 3.2.9 - - 3.2.7 - - 3.2.6 include: - compatibilityVersion: 3.4.2 coherence-image: "ghcr.io/oracle/coherence-ce:14.1.2-0-1" @@ -96,18 +93,6 @@ jobs: coherence-image: "ghcr.io/oracle/coherence-ce:22.06.10" compatibilitySelector: control-plane=coherence k8s: kindest/node:v1.26.6@sha256:6e2d8b28a5b601defe327b98bd1c2d1930b49e5d8c512e1895099e4504007adb - - compatibilityVersion: 3.2.9 - coherence-image: "ghcr.io/oracle/coherence-ce:22.06.10" - compatibilitySelector: control-plane=coherence - k8s: kindest/node:v1.24.12@sha256:1e12918b8bc3d4253bc08f640a231bb0d3b2c5a9b28aa3f2ca1aee93e1e8db16 - - compatibilityVersion: 3.2.7 - coherence-image: "ghcr.io/oracle/coherence-ce:22.06.10" - compatibilitySelector: control-plane=coherence - k8s: kindest/node:v1.24.12@sha256:1e12918b8bc3d4253bc08f640a231bb0d3b2c5a9b28aa3f2ca1aee93e1e8db16 - - compatibilityVersion: 3.2.6 - coherence-image: "ghcr.io/oracle/coherence-ce:22.06.10" - compatibilitySelector: control-plane=coherence - k8s: kindest/node:v1.24.12@sha256:1e12918b8bc3d4253bc08f640a231bb0d3b2c5a9b28aa3f2ca1aee93e1e8db16 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ef14d60f6..418ea106a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -161,4 +161,15 @@ jobs: upload_url: ${{ github.event.release.upload_url }} asset_path: /tmp/coherence-operator/_output/coherence-dashboards.tar.gz asset_name: coherence-dashboards.tar.gz - asset_content_type: text/plain + asset_content_type: application/tar+gzip + + - name: Upload Docs + id: upload-docs + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: /tmp/coherence-operator/_output/docs.tar.gz + asset_name: docs.tar.gz + asset_content_type: application/tar+gzip diff --git a/Dockerfile b/Dockerfile index d2765f72f..288cf2c0c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,18 +10,34 @@ ARG target ARG version ARG coherence_image ARG operator_image +ARG release LABEL "com.oracle.coherence.application"="operator" LABEL "com.oracle.coherence.version"="$version" +LABEL "org.opencontainers.image.revision"="$release" LABEL "org.opencontainers.image.description"="The Oracle Coherece Kubernetes Operator image ($target)" LABEL "org.opencontainers.image.source"="https://github.com/oracle/coherence-operator" +LABEL "org.opencontainers.image.authors"="To contact the authors use this link https://github.com/oracle/coherence-operator/discussions" +LABEL "org.opencontainers.image.licenses"="UPL-1.0" +LABEL "org.opencontainers.image.description"="The Oracle Coherece Kubernetes Operator allows full lifecycle management of Oracle Coherence workloads in Kubernetes." + +LABEL "name"="Oracle Coherence Kubernetes Operator" +LABEL "vendor"="Oracle" +LABEL "version"="$version" +LABEL "release"="$release" +LABEL "maintainer"="Oracle Coherence Engieering Team" +LABEL "summary"="A Kubernetes Operator for managing Oracle Coherence clusters" +LABEL "description"="The Oracle Coherece Kubernetes Operator allows full lifecycle management of Oracle Coherence workloads in Kubernetes." ENV COHERENCE_IMAGE=$coherence_image \ OPERATOR_IMAGE=$operator_image +COPY LICENSE.txt /licenses/LICENSE.txt 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 +USER 1000 + ENTRYPOINT ["/files/runner"] CMD ["-h"] diff --git a/Makefile b/Makefile index 55e1ac1ad..09f6d4a48 100644 --- a/Makefile +++ b/Makefile @@ -71,6 +71,12 @@ else GH_AUTH := 'authorization: Bearer $(GH_TOKEN)' endif +# defines $n to be a newline character which is useful in messages +define n + + +endef + # ---------------------------------------------------------------------------------------------------------------------- # By default we target amd64 as this is by far the most common local build environment # We actually build images for amd64 and arm64 @@ -91,7 +97,7 @@ GOPROXY ?= https://proxy.golang.org # ---------------------------------------------------------------------------------------------------------------------- # Set the location of the Operator SDK executable # ---------------------------------------------------------------------------------------------------------------------- -OPERATOR_SDK_VERSION := v1.9.0 +OPERATOR_SDK_VERSION := v1.39.1 # ---------------------------------------------------------------------------------------------------------------------- # Options to append to the Maven command @@ -102,44 +108,38 @@ MAVEN_BUILD_OPTS :=$(USE_MAVEN_SETTINGS) -Drevision=$(MVN_VERSION) -Dcoherence.v # ---------------------------------------------------------------------------------------------------------------------- # Operator image names # ---------------------------------------------------------------------------------------------------------------------- -BASE_IMAGE_REGISTRY ?= ghcr.io -BASE_IMAGE_REPO ?= oracle -OPERATOR_IMAGE_REGISTRY ?= $(BASE_IMAGE_REGISTRY)/$(BASE_IMAGE_REPO) -RELEASE_IMAGE_PREFIX ?= $(OPERATOR_IMAGE_REGISTRY)/ -OPERATOR_IMAGE_NAME := coherence-operator +OPERATOR_IMAGE_REGISTRY ?= ghcr.io/oracle OPERATOR_BASE_IMAGE ?= scratch -OPERATOR_OL_BASE_IMAGE ?= container-registry.oracle.com/java/jdk:17 -OPERATOR_IMAGE_REPO := $(RELEASE_IMAGE_PREFIX)$(OPERATOR_IMAGE_NAME) -OPERATOR_IMAGE := $(OPERATOR_IMAGE_REPO):$(VERSION) -OPERATOR_IMAGE_DELVE := $(OPERATOR_IMAGE_REPO):delve -OPERATOR_IMAGE_DEBUG := $(OPERATOR_IMAGE_REPO):debug -TEST_BASE_IMAGE ?= $(OPERATOR_IMAGE_REPO)-test-base:$(VERSION) -# The Operator images to push -OPERATOR_RELEASE_REPO ?= $(OPERATOR_IMAGE_REPO) -OPERATOR_RELEASE_IMAGE := $(OPERATOR_RELEASE_REPO):$(VERSION) -TEST_BASE_RELEASE_IMAGE := $(OPERATOR_RELEASE_REPO)-test-base:$(VERSION) -BUNDLE_RELEASE_IMAGE := $(OPERATOR_RELEASE_REPO)-bundle:$(VERSION) - -OPERATOR_PACKAGE_PREFIX := $(OPERATOR_IMAGE_REPO)-package -OPERATOR_PACKAGE_IMAGE := $(OPERATOR_PACKAGE_PREFIX):$(VERSION) -OPERATOR_REPO_PREFIX := $(OPERATOR_IMAGE_REPO)-repo -OPERATOR_REPO_IMAGE := $(OPERATOR_REPO_PREFIX):$(VERSION) +OPERATOR_IMAGE_NAME := coherence-operator +OPERATOR_IMAGE_ARM := $(OPERATOR_IMAGE_REGISTRY)/$(OPERATOR_IMAGE_NAME):$(VERSION)-arm64 +OPERATOR_IMAGE_AMD := $(OPERATOR_IMAGE_REGISTRY)/$(OPERATOR_IMAGE_NAME):$(VERSION)-amd64 +OPERATOR_IMAGE := $(OPERATOR_IMAGE_REGISTRY)/$(OPERATOR_IMAGE_NAME):$(VERSION) +OPERATOR_IMAGE_DELVE := $(OPERATOR_IMAGE_REGISTRY)/$(OPERATOR_IMAGE_NAME):delve +OPERATOR_IMAGE_DEBUG := $(OPERATOR_IMAGE_REGISTRY)/$(OPERATOR_IMAGE_NAME):debug + +TEST_BASE_IMAGE := $(OPERATOR_IMAGE_REGISTRY)/$(OPERATOR_IMAGE_NAME)-test-base:$(VERSION) + +# Tanzu packages +OPERATOR_PACKAGE_PREFIX := $(OPERATOR_IMAGE_REGISTRY)/$(OPERATOR_IMAGE_NAME)-package +OPERATOR_PACKAGE_IMAGE := $(OPERATOR_PACKAGE_PREFIX):$(VERSION) +OPERATOR_REPO_PREFIX := $(OPERATOR_IMAGE_REGISTRY)/$(OPERATOR_IMAGE_NAME)-repo +OPERATOR_REPO_IMAGE := $(OPERATOR_REPO_PREFIX):$(VERSION) # ---------------------------------------------------------------------------------------------------------------------- # The test application images used in integration tests # ---------------------------------------------------------------------------------------------------------------------- -TEST_APPLICATION_IMAGE := $(RELEASE_IMAGE_PREFIX)operator-test:1.0.0 -TEST_COMPATIBILITY_IMAGE := $(RELEASE_IMAGE_PREFIX)operator-test-compatibility:1.0.0 -TEST_APPLICATION_IMAGE_CLIENT := $(RELEASE_IMAGE_PREFIX)operator-test-client:1.0.0 -TEST_APPLICATION_IMAGE_HELIDON := $(RELEASE_IMAGE_PREFIX)operator-test-helidon:1.0.0 -TEST_APPLICATION_IMAGE_HELIDON_3 := $(RELEASE_IMAGE_PREFIX)operator-test-helidon-3:1.0.0 -TEST_APPLICATION_IMAGE_HELIDON_2 := $(RELEASE_IMAGE_PREFIX)operator-test-helidon-2:1.0.0 -TEST_APPLICATION_IMAGE_SPRING := $(RELEASE_IMAGE_PREFIX)operator-test-spring:1.0.0 -TEST_APPLICATION_IMAGE_SPRING_FAT := $(RELEASE_IMAGE_PREFIX)operator-test-spring-fat:1.0.0 -TEST_APPLICATION_IMAGE_SPRING_CNBP := $(RELEASE_IMAGE_PREFIX)operator-test-spring-cnbp:1.0.0 -TEST_APPLICATION_IMAGE_SPRING_2 := $(RELEASE_IMAGE_PREFIX)operator-test-spring-2:1.0.0 -TEST_APPLICATION_IMAGE_SPRING_FAT_2 := $(RELEASE_IMAGE_PREFIX)operator-test-spring-fat-2:1.0.0 -TEST_APPLICATION_IMAGE_SPRING_CNBP_2 := $(RELEASE_IMAGE_PREFIX)operator-test-spring-cnbp-2:1.0.0 +TEST_APPLICATION_IMAGE := $(OPERATOR_IMAGE_REGISTRY)/operator-test:1.0.0 +TEST_COMPATIBILITY_IMAGE := $(OPERATOR_IMAGE_REGISTRY)/operator-test-compatibility:1.0.0 +TEST_APPLICATION_IMAGE_CLIENT := $(OPERATOR_IMAGE_REGISTRY)/operator-test-client:1.0.0 +TEST_APPLICATION_IMAGE_HELIDON := $(OPERATOR_IMAGE_REGISTRY)/operator-test-helidon:1.0.0 +TEST_APPLICATION_IMAGE_HELIDON_3 := $(OPERATOR_IMAGE_REGISTRY)/operator-test-helidon-3:1.0.0 +TEST_APPLICATION_IMAGE_HELIDON_2 := $(OPERATOR_IMAGE_REGISTRY)/operator-test-helidon-2:1.0.0 +TEST_APPLICATION_IMAGE_SPRING := $(OPERATOR_IMAGE_REGISTRY)/operator-test-spring:1.0.0 +TEST_APPLICATION_IMAGE_SPRING_FAT := $(OPERATOR_IMAGE_REGISTRY)/operator-test-spring-fat:1.0.0 +TEST_APPLICATION_IMAGE_SPRING_CNBP := $(OPERATOR_IMAGE_REGISTRY)/operator-test-spring-cnbp:1.0.0 +TEST_APPLICATION_IMAGE_SPRING_2 := $(OPERATOR_IMAGE_REGISTRY)/operator-test-spring-2:1.0.0 +TEST_APPLICATION_IMAGE_SPRING_FAT_2 := $(OPERATOR_IMAGE_REGISTRY)/operator-test-spring-fat-2:1.0.0 +TEST_APPLICATION_IMAGE_SPRING_CNBP_2 := $(OPERATOR_IMAGE_REGISTRY)/operator-test-spring-cnbp-2:1.0.0 # ---------------------------------------------------------------------------------------------------------------------- # Operator Lifecycle Manager properties @@ -167,7 +167,7 @@ BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) # BUNDLE_IMG defines the image:tag used for the bundle. # You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) -BUNDLE_IMG ?= $(OPERATOR_IMAGE_REPO)-bundle:$(VERSION) +BUNDLE_IMAGE := $(OPERATOR_IMAGE_REGISTRY)/$(OPERATOR_IMAGE_NAME)-bundle:$(VERSION) # ---------------------------------------------------------------------------------------------------------------------- # Release build options @@ -209,6 +209,7 @@ LOCAL_STORAGE_RESTART ?= false # This is required if building and testing in environments that need to pull or push # images to private registries. For example building and testing with k8s in OCI. # ---------------------------------------------------------------------------------------------------------------------- +DOCKER_CMD ?= docker DOCKER_SERVER ?= DOCKER_USERNAME ?= DOCKER_PASSWORD ?= @@ -275,6 +276,7 @@ override BUILD_MANIFESTS := $(BUILD_OUTPUT)/manifests override BUILD_MANIFESTS_PKG := $(BUILD_OUTPUT)/coherence-operator-manifests.tar.gz override BUILD_PROPS := $(BUILD_OUTPUT)/build.properties override BUILD_TARGETS := $(BUILD_OUTPUT)/targets +override BUILD_PREFLIGHT := $(BUILD_OUTPUT)/preflight override SCRIPTS_DIR := $(CURRDIR)/hack override EXAMPLES_DIR := $(CURRDIR)/examples override TEST_LOGS_DIR := $(BUILD_OUTPUT)/test-logs @@ -350,6 +352,7 @@ HELM_FILES = $(shell find helm-charts/coherence-operator -type f) API_GO_FILES = $(shell find . -type f -name "*.go" ! -name "*_test.go" ! -name "zz*.go") CRDV1_FILES = $(shell find ./config/crd -type f) JAVA_FILES = $(shell find ./java -type f) +MANIFEST_FILES = $(shell find ./config -type f) TEST_SSL_SECRET := coherence-ssl-secret @@ -442,7 +445,6 @@ $(BUILD_PROPS): COHERENCE_IMAGE_NAME=$(COHERENCE_IMAGE_NAME)\n\ COHERENCE_IMAGE_TAG=$(COHERENCE_IMAGE_TAG)\n\ OPERATOR_IMAGE_REGISTRY=$(OPERATOR_IMAGE_REGISTRY)\n\ - RELEASE_IMAGE_PREFIX=$(RELEASE_IMAGE_PREFIX)\n\ OPERATOR_IMAGE_NAME=$(OPERATOR_IMAGE_NAME)\n\ OPERATOR_IMAGE=$(OPERATOR_IMAGE)\n\ VERSION=$(VERSION)\n\ @@ -482,50 +484,50 @@ clean-tools: ## Cleans the locally downloaded build tools (i.e. need a new tool build-operator: $(BUILD_TARGETS)/build-operator ## Build the Coherence Operator image $(BUILD_TARGETS)/build-operator: $(BUILD_BIN)/runner $(BUILD_TARGETS)/java $(BUILD_TARGETS)/cli - docker build --platform linux/amd64 --no-cache --build-arg version=$(VERSION) \ - --build-arg BASE_IMAGE=$(OPERATOR_BASE_IMAGE) \ - --build-arg coherence_image=$(COHERENCE_IMAGE) \ - --build-arg operator_image=$(OPERATOR_IMAGE) \ - --build-arg release=$(GITCOMMIT) \ - --build-arg target=amd64 \ - . -t $(OPERATOR_IMAGE)-amd64 - docker build --platform linux/arm64 --no-cache --build-arg version=$(VERSION) \ - --build-arg BASE_IMAGE=$(OPERATOR_BASE_IMAGE) \ + $(call buildOperatorImage,$(OPERATOR_BASE_IMAGE),amd64,$(OPERATOR_IMAGE)) + $(call buildOperatorImage,$(OPERATOR_BASE_IMAGE),arm64,$(OPERATOR_IMAGE)) + $(DOCKER_CMD) tag $(OPERATOR_IMAGE)-$(IMAGE_ARCH) $(OPERATOR_IMAGE) + touch $(BUILD_TARGETS)/build-operator + +define buildOperatorImage + $(DOCKER_CMD) build --platform linux/$(2) --no-cache --build-arg version=$(VERSION) \ + --build-arg BASE_IMAGE=$(1) \ --build-arg coherence_image=$(COHERENCE_IMAGE) \ - --build-arg operator_image=$(OPERATOR_IMAGE) \ + --build-arg operator_image=$(3) \ --build-arg release=$(GITCOMMIT) \ - --build-arg target=arm64 \ - . -t $(OPERATOR_IMAGE)-arm64 - docker tag $(OPERATOR_IMAGE)-$(IMAGE_ARCH) $(OPERATOR_IMAGE) - touch $(BUILD_TARGETS)/build-operator + --build-arg target=$(2) \ + --load -t $(3)-$(2) . +endef + +OPERATOR_OL_BASE_IMAGE ?= container-registry.oracle.com/java/jdk:17 .PHONY: build-operator-with-tools build-operator-with-tools: $(BUILD_BIN)/runner $(BUILD_TARGETS)/java ## Build the Coherence Operator image on OL-8 with debug tools mkdir -p $(BUILD_OUTPUT)/images || true cat Dockerfile debug/Tools.Dockerfile > $(BUILD_OUTPUT)/images/Dockerfile - docker build --no-cache --build-arg version=$(VERSION) \ + $(DOCKER_CMD) build --no-cache --build-arg version=$(VERSION) \ --build-arg BASE_IMAGE=$(OPERATOR_OL_BASE_IMAGE) \ --build-arg coherence_image=$(COHERENCE_IMAGE) \ --build-arg operator_image=$(OPERATOR_IMAGE) \ --build-arg target=amd64 \ -f $(BUILD_OUTPUT)/images/Dockerfile \ - . -t $(OPERATOR_IMAGE) + --load -t $(OPERATOR_IMAGE) . .PHONY: build-operator-debug build-operator-debug: $(BUILD_TARGETS)/delve-image $(BUILD_BIN)/runner-debug $(BUILD_TARGETS)/java ## Build the Coherence Operator image with the Delve debugger - docker build --platform linux/$(IMAGE_ARCH) --no-cache --build-arg version=$(VERSION) \ + $(DOCKER_CMD) build --platform linux/$(IMAGE_ARCH) --no-cache --build-arg version=$(VERSION) \ --build-arg coherence_image=$(COHERENCE_IMAGE) \ --build-arg operator_image=$(OPERATOR_IMAGE) \ --build-arg target=$(IMAGE_ARCH) \ -f debug/Dockerfile \ - . -t $(OPERATOR_IMAGE_DEBUG) + --load -t $(OPERATOR_IMAGE_DEBUG) . .PHONY: build-delve-image build-delve-image: $(BUILD_TARGETS)/delve-image ## Build the Coherence Operator Delve debugger base image $(BUILD_TARGETS)/delve-image: GV=$(GO_VERSION) && GVS="$${GV#go}" && \ - docker build --build-arg BASE_IMAGE=golang:$${GVS} -f debug/Base.Dockerfile -t $(OPERATOR_IMAGE_DELVE) debug + $(DOCKER_CMD) build --build-arg BASE_IMAGE=golang:$${GVS} -f debug/Base.Dockerfile -t $(OPERATOR_IMAGE_DELVE) --load debug touch $(BUILD_TARGETS)/delve-image $(BUILD_BIN)/runner-debug: $(BUILD_PROPS) $(GOS) $(BUILD_TARGETS)/generate $(BUILD_TARGETS)/manifests @@ -569,23 +571,23 @@ build-test-images: $(BUILD_TARGETS)/java build-client-image build-basic-test-ima # Spring Boot 3.x CNBP ./mvnw -B -f java/operator-test-spring package spring-boot:build-image -DskipTests -Dcnbp-image-name=$(TEST_APPLICATION_IMAGE_SPRING_CNBP) $(MAVEN_BUILD_OPTS) # Spring Boot 3.x fat jar - docker build -f java/operator-test-spring/target/FatJar.Dockerfile -t $(TEST_APPLICATION_IMAGE_SPRING_FAT) java/operator-test-spring/target + $(DOCKER_CMD) build -f java/operator-test-spring/target/FatJar.Dockerfile -t $(TEST_APPLICATION_IMAGE_SPRING_FAT) --load java/operator-test-spring/target # Spring Boot 3.x exploded fat jar rm -rf java/operator-test-spring/target/spring || true && mkdir java/operator-test-spring/target/spring cp java/operator-test-spring/target/operator-test-spring-$(MVN_VERSION).jar java/operator-test-spring/target/spring/operator-test-spring-$(MVN_VERSION).jar cd java/operator-test-spring/target/spring && jar -xvf operator-test-spring-$(MVN_VERSION).jar && rm -f operator-test-spring-$(MVN_VERSION).jar - docker build -f java/operator-test-spring/target/Dir.Dockerfile -t $(TEST_APPLICATION_IMAGE_SPRING) java/operator-test-spring/target + $(DOCKER_CMD) build -f java/operator-test-spring/target/Dir.Dockerfile -t $(TEST_APPLICATION_IMAGE_SPRING) --load java/operator-test-spring/target # Spring Boot 2.x JIB ./mvnw -B -f java/operator-test-spring-2 package jib:dockerBuild -DskipTests -Djib.to.image=$(TEST_APPLICATION_IMAGE_SPRING_2) $(MAVEN_BUILD_OPTS) # Spring Boot 2.x CNBP ./mvnw -B -f java/operator-test-spring-2 package spring-boot:build-image -DskipTests -Dcnbp-image-name=$(TEST_APPLICATION_IMAGE_SPRING_CNBP_2) $(MAVEN_BUILD_OPTS) # Spring Boot 2.x fat jar - docker build -f java/operator-test-spring-2/target/FatJar.Dockerfile -t $(TEST_APPLICATION_IMAGE_SPRING_FAT_2) java/operator-test-spring-2/target + $(DOCKER_CMD) build -f java/operator-test-spring-2/target/FatJar.Dockerfile -t $(TEST_APPLICATION_IMAGE_SPRING_FAT_2) --load java/operator-test-spring-2/target # Spring Boot 2.x exploded fat jar rm -rf java/operator-test-spring-2/target/spring || true && mkdir java/operator-test-spring-2/target/spring cp java/operator-test-spring-2/target/operator-test-spring-2-$(MVN_VERSION).jar java/operator-test-spring-2/target/spring/operator-test-spring-2-$(MVN_VERSION).jar cd java/operator-test-spring-2/target/spring && jar -xvf operator-test-spring-2-$(MVN_VERSION).jar && rm -f operator-test-spring-2-$(MVN_VERSION).jar - docker build -f java/operator-test-spring-2/target/Dir.Dockerfile -t $(TEST_APPLICATION_IMAGE_SPRING_2) java/operator-test-spring-2/target + $(DOCKER_CMD) build -f java/operator-test-spring-2/target/Dir.Dockerfile -t $(TEST_APPLICATION_IMAGE_SPRING_2) --load java/operator-test-spring-2/target # ---------------------------------------------------------------------------------------------------------------------- # Build the basic Operator Test image @@ -683,7 +685,7 @@ endef .PHONY: manifests manifests: $(BUILD_TARGETS)/manifests ## Generate the CustomResourceDefinition and other yaml manifests. -$(BUILD_TARGETS)/manifests: $(BUILD_PROPS) config/crd/bases/coherence.oracle.com_coherence.yaml docs/about/04_coherence_spec.adoc $(BUILD_MANIFESTS_PKG) +$(BUILD_TARGETS)/manifests: $(BUILD_PROPS) config/crd/bases/coherence.oracle.com_coherence.yaml docs/about/04_coherence_spec.adoc $(MANIFEST_FILES) $(BUILD_MANIFESTS_PKG) touch $(BUILD_TARGETS)/manifests config/crd/bases/coherence.oracle.com_coherence.yaml: $(TOOLS_BIN)/kustomize $(API_GO_FILES) $(TOOLS_BIN)/controller-gen @@ -708,7 +710,7 @@ $(BUILD_OUTPUT)/config.json: @echo "Generating Operator config" @printf "{\n \ \"coherence-image\": \"$(COHERENCE_IMAGE)\",\n \ - \"operator-image\": \"$(OPERATOR_RELEASE_IMAGE)\"\n}\n" > $(BUILD_OUTPUT)/config.json + \"operator-image\": \"$(OPERATOR_IMAGE)\"\n}\n" > $(BUILD_OUTPUT)/config.json cp $(BUILD_OUTPUT)/config.json $(BUILD_ASSETS)/config.json # ---------------------------------------------------------------------------------------------------------------------- @@ -889,24 +891,27 @@ stop: ## kill any locally running operator process # Generate bundle manifests and metadata, then validate generated files. # ---------------------------------------------------------------------------------------------------------------------- .PHONY: bundle -bundle: $(BUILD_PROPS) ensure-sdk $(TOOLS_BIN)/kustomize $(BUILD_TARGETS)/manifests ## Generate OLM bundle manifests and metadata, then validate generated files. - $(OPERATOR_SDK) generate kustomize manifests -q +bundle: $(BUILD_PROPS) ensure-sdk $(TOOLS_BIN)/kustomize $(BUILD_TARGETS)/manifests $(MANIFEST_FILES) ## Generate OLM bundle manifests and metadata, then validate generated files. + $(OPERATOR_SDK) generate kustomize manifests cd config/manager && $(KUSTOMIZE) edit set image controller=$(OPERATOR_IMAGE) $(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) $(OPERATOR_SDK) bundle validate ./bundle - $(OPERATOR_SDK) bundle validate ./bundle --select-optional suite=operatorframework --optional-values=k8s-version=1.22 - $(OPERATOR_SDK) bundle validate ./bundle --select-optional name=community --optional-values=image-path=bundle.Dockerfile + $(OPERATOR_SDK) bundle validate ./bundle --select-optional suite=operatorframework --optional-values=k8s-version=1.26 + $(OPERATOR_SDK) bundle validate ./bundle --select-optional name=operatorhubv2 --optional-values=k8s-version=1.26 + $(OPERATOR_SDK) bundle validate ./bundle --select-optional name=capabilities --optional-values=k8s-version=1.26 + $(OPERATOR_SDK) bundle validate ./bundle --select-optional name=categories --optional-values=k8s-version=1.26 + rm -rf bundle_tmp* # ---------------------------------------------------------------------------------------------------------------------- # Build the bundle image. # ---------------------------------------------------------------------------------------------------------------------- -.PHONY: bundle-build -bundle-build: ## Build the OLM image - docker build --no-cache -f bundle.Dockerfile -t $(BUNDLE_IMG) . +.PHONY: bundle-image +bundle-image: bundle ## Build the OLM image + $(DOCKER_CMD) build --no-cache -f bundle.Dockerfile -t $(BUNDLE_IMAGE) --load . .PHONY: bundle-push bundle-push: ## Push the OLM bundle image. - $(MAKE) docker-push IMG=$(BUNDLE_IMG) + $(DOCKER_CMD) push $(OPE) $(BUNDLE_IMAGE) .PHONY: opm OPM = ./bin/opm @@ -925,14 +930,14 @@ OPM = $(shell which opm) endif endif -# A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0). +# A comma-separated list of bundle images # These images MUST exist in a registry and be pull-able. -BUNDLE_IMGS ?= $(BUNDLE_IMG) +BUNDLE_IMAGE_LIST ?= $(BUNDLE_IMAGE) -# The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0). -CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION) +# The image tag given to the resulting catalog image +CATALOG_IMAGE := $(OPERATOR_IMAGE_REGISTRY)/$(OPERATOR_IMAGE_NAME)-catalog:$(VERSION) -# Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image. +# Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMAGE_LIST to that image. ifneq ($(origin CATALOG_BASE_IMG), undefined) FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG) endif @@ -941,14 +946,116 @@ endif # This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see: # https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator .PHONY: catalog-build -catalog-build: opm ## Build an OLM catalog image. - $(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT) +catalog-build: opm ## Build a catalog image. + $(OPM) index add --container-tool $(DOCKER_CMD) --mode semver --tag $(CATALOG_IMAGE) --bundles $(BUNDLE_IMAGE_LIST) $(FROM_INDEX_OPT) # Push the catalog image. .PHONY: catalog-push -catalog-push: ## Push an OLM catalog image. - $(MAKE) docker-push IMG=$(CATALOG_IMG) +catalog-push: ## Push a catalog image. + $(DOCKER_CMD) push $(CATALOG_IMAGE) +.PHONY: scorecard +scorecard: $(BUILD_PROPS) ensure-sdk bundle ## Run the Operator SDK scorecard tests. + $(OPERATOR_SDK) scorecard ./bundle + +# ====================================================================================================================== +# Targets to run a local container registry +# ====================================================================================================================== +REGISTRY_USER ?= operator +REGISTRY_PWD ?= secret + +$(TOOLS_DIRECTORY)/registry/auth/htpasswd: + mkdir -p ${TOOLS_DIRECTORY}/registry/{auth,certs,data} || true + htpasswd -bBc ${TOOLS_DIRECTORY}/registry/auth/htpasswd $(REGISTRY_USER) $(REGISTRY_PWD) + +.PHONY: registry +registry: $(TOOLS_DIRECTORY)/registry/auth/htpasswd + mkdir -p ${TOOLS_DIRECTORY}/registry/{auth,certs,data} || true + openssl req -newkey rsa:4096 -nodes -sha256 \ + -keyout $(TOOLS_DIRECTORY)/registry/certs/domain.key \ + -x509 -days 3650 -subj "/CN=localhost" \ + -addext "subjectAltName = DNS:registry" \ + -out $(TOOLS_DIRECTORY)/registry/certs/domain.crt + $(DOCKER_CMD) network create registry-network || true + $(DOCKER_CMD) run --name registry --network registry-network \ + -p 5555:5000 \ + -v ${TOOLS_DIRECTORY}/registry/data:/var/lib/registry:z \ + -v ${TOOLS_DIRECTORY}/registry/auth:/auth:z \ + -e "REGISTRY_AUTH=htpasswd" \ + -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ + -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \ + -v ${TOOLS_DIRECTORY}/registry/certs:/certs:z \ + -e "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt" \ + -e "REGISTRY_HTTP_TLS_KEY=/certs/domain.key" \ + -e REGISTRY_COMPATIBILITY_SCHEMA1_ENABLED=true \ + -d docker.io/library/registry:latest + $(DOCKER_CMD) login localhost:5555 -u $(REGISTRY_USER) -p $(REGISTRY_PWD) + +.PHONY: registry-stop +registry-stop: + $(DOCKER_CMD) rm -f registry + +# ====================================================================================================================== +# Targets for OpenShift - requires various OpenShift CLI tools +# ====================================================================================================================== +##@ OpenShift related tasks + +.PHONY: preflight +preflight: ## Run the OpenShift preflight tests against the Operator Image in a container + mkdir -p $(BUILD_PREFLIGHT) || true + $(DOCKER_CMD) network create registry-network || true + $(DOCKER_CMD) run -it --rm --network registry-network \ + --security-opt=label=disable \ + --env KUBECONFIG=/kubeconfig/config \ + --env PFLT_DOCKERCONFIG=/dockerconfig/config.json \ + --env PFLT_LOGLEVEL=trace \ + --env PFLT_CHANNEL=beta \ + --env PFLT_LOGFILE=/artifacts/preflight.log \ + -v $(BUILD_PREFLIGHT):/artifacts \ + -v $(HOME)/.kube/:/kubeconfig:ro \ + -v $(SCRIPTS_DIR):/dockerconfig:ro \ + quay.io/opdev/preflight:stable check container --insecure $(OPERATOR_IMAGE) + +.PHONY: preflight-oc +preflight-oc: $(BUILD_PREFLIGHT)/preflight.yaml preflight-oc-cleanup ## Run the OpenShift preflight tests as a K8s Job against the Operator Image + oc apply -f $(BUILD_PREFLIGHT)/preflight.yaml + oc wait --for condition=complete job/preflight --timeout 480s + oc logs job/preflight > $(BUILD_PREFLIGHT)/preflight.log || true + +.PHONY: preflight-oc-cleanup +preflight-oc-cleanup: $(BUILD_PREFLIGHT)/preflight.yaml ## Clean up the OpenShift preflight tests Job + oc delete -f $(BUILD_PREFLIGHT)/preflight.yaml || true + +# This variable should be passed in and is the credentials for the container registry +# that holds the Operator Image to be pulled by the preflight Job. +# This is usually obtained by running: +# echo -n bogus:$(oc whoami -t) | base64 +PREFLIGHT_REGISTRY_CRED ?= + +.PHONY: jk +jk: $(BUILD_PREFLIGHT)/preflight.yaml + +# Generate the preflight job yaml +$(BUILD_PREFLIGHT)/preflight.yaml: hack/preflight.yaml +#ifeq ($(PREFLIGHT_REGISTRY_CRED),) +# $(error $(n)The PREFLIGHT_REGISTRY_CRED variable must be specified to run preflight$(n)Typically using the command$(n)$(n) export PREFLIGHT_REGISTRY_CRED=$$(echo -n bogus:$$(oc whoami -t) | base64)$(n)$(n)) +#endif + cp hack/preflight.yaml $(BUILD_PREFLIGHT)/preflight.yaml + $(SED) -e 's^image-placeholder^$(OPERATOR_IMAGE)^g' $(BUILD_PREFLIGHT)/preflight.yaml + $(SED) -e 's/registry-credential-placeholder/$(PREFLIGHT_REGISTRY_CRED)/g' $(BUILD_PREFLIGHT)/preflight.yaml + +.PHONY: oc-login +oc-login: + oc login -u kubeadmin https://api.crc.testing:6443 + +# REGISTRY=$(oc get route/default-route -n openshift-image-registry -o=jsonpath='{.spec.host}') +# OPERATOR_RELEASE_REGISTRY=${REGISTRY}/oracle +# podman login -u bogus -p $(oc whoami -t) --tls-verify=false $REGISTRY +# creds for auth config: echo -n bogus:$(oc whoami -t) | base64 +# Allow operator-test:coherence-operator-service-account in operator-test to pull images +# oc policy add-role-to-user system:image-puller system:serviceaccount:operator-test:coherence-operator-service-account --namespace=oracle +# Allow anything in operator-test to pull images +# oc policy add-role-to-user system:image-puller system:serviceaccounts:operator-test --namespace=oracle # ====================================================================================================================== # Targets to run various tests @@ -1306,7 +1413,7 @@ run-certification: export TEST_IMAGE_PULL_POLICY := $(IMAGE_PULL_POLICY) run-certification: export TEST_STORAGE_CLASS := $(TEST_STORAGE_CLASS) run-certification: export VERSION := $(VERSION) run-certification: export CERTIFICATION_VERSION := $(CERTIFICATION_VERSION) -run-certification: export OPERATOR_IMAGE_REPO := $(OPERATOR_IMAGE_REPO) +run-certification: export OPERATOR_IMAGE_REPO := $(OPERATOR_IMAGE_REGISTRY)/$(OPERATOR_IMAGE_NAME) run-certification: export OPERATOR_IMAGE := $(OPERATOR_IMAGE) run-certification: export COHERENCE_IMAGE := $(COHERENCE_IMAGE) run-certification: gotestsum @@ -1445,7 +1552,7 @@ run-coherence-compatibility: export TEST_IMAGE_PULL_POLICY := $(IMAGE_PULL_POLIC run-coherence-compatibility: export TEST_STORAGE_CLASS := $(TEST_STORAGE_CLASS) run-coherence-compatibility: export VERSION := $(VERSION) run-coherence-compatibility: export CERTIFICATION_VERSION := $(CERTIFICATION_VERSION) -run-coherence-compatibility: export OPERATOR_IMAGE_REPO := $(OPERATOR_IMAGE_REPO) +run-coherence-compatibility: export OPERATOR_IMAGE_REPO := $(OPERATOR_IMAGE_REGISTRY)/$(OPERATOR_IMAGE_NAME) run-coherence-compatibility: export OPERATOR_IMAGE := $(OPERATOR_IMAGE) run-coherence-compatibility: export COHERENCE_IMAGE := $(COHERENCE_IMAGE) run-coherence-compatibility: gotestsum $(BUILD_TARGETS)/generate @@ -1508,7 +1615,8 @@ endif .PHONY: just-deploy just-deploy: ## Deploy the Coherence Operator without rebuilding anything - $(call do_deploy,$(OPERATOR_IMAGE),$(OPERATOR_NAMESPACE)) + $(call prepare_deploy,$(OPERATOR_IMAGE),$(OPERATOR_NAMESPACE)) + $(KUSTOMIZE) build $(BUILD_DEPLOY)/default | kubectl apply -f - .PHONY: prepare-deploy prepare-deploy: $(BUILD_TARGETS)/manifests $(BUILD_TARGETS)/build-operator $(TOOLS_BIN)/kustomize @@ -1572,11 +1680,6 @@ define prepare_deploy cd $(BUILD_DEPLOY)/default && $(KUSTOMIZE) edit set namespace $(2) endef -define do_deploy - $(call prepare_deploy,$(1),$(2)) - $(KUSTOMIZE) build $(BUILD_DEPLOY)/default | kubectl apply -f - -endef - # ---------------------------------------------------------------------------------------------------------------------- # Un-deploy controller from the configured Kubernetes cluster in ~/.kube/config @@ -1601,7 +1704,7 @@ tail-logs: ## Tail the Coherence Operator Pod logs (with follow) kubectl -n $(OPERATOR_NAMESPACE) logs $(POD) -c manager -f -$(BUILD_MANIFESTS_PKG): $(TOOLS_BIN)/kustomize $(TOOLS_BIN)/yq +$(BUILD_MANIFESTS_PKG): $(TOOLS_BIN)/kustomize $(TOOLS_BIN)/yq $(MANIFEST_FILES) rm -rf $(BUILD_MANIFESTS) || true mkdir -p $(BUILD_MANIFESTS)/crd $(KUSTOMIZE) build config/crd > $(BUILD_MANIFESTS)/crd/temp.yaml @@ -1825,7 +1928,7 @@ kind-load: kind-load-operator kind-load-coherence ## Load all images into the K .PHONY: kind-load-coherence kind-load-coherence: ## Load the Coherence image into the KinD cluster - docker pull $(COHERENCE_IMAGE) + $(DOCKER_CMD) pull $(COHERENCE_IMAGE) kind load docker-image --name $(KIND_CLUSTER) $(COHERENCE_IMAGE) .PHONY: kind-load-operator @@ -2190,77 +2293,60 @@ test-examples: build-examples # ---------------------------------------------------------------------------------------------------------------------- # Push the Operator Docker image # ---------------------------------------------------------------------------------------------------------------------- +PUSH_ARGS ?= + .PHONY: push-operator-image push-operator-image: $(BUILD_TARGETS)/build-operator -ifeq ($(OPERATOR_RELEASE_IMAGE), $(OPERATOR_IMAGE)) - @echo "Pushing $(OPERATOR_IMAGE)" - docker push $(OPERATOR_IMAGE)-amd64 - docker push $(OPERATOR_IMAGE)-arm64 - docker manifest create $(OPERATOR_IMAGE) \ - --amend $(OPERATOR_IMAGE)-amd64 \ - --amend $(OPERATOR_IMAGE)-arm64 - docker manifest annotate $(OPERATOR_IMAGE) $(OPERATOR_IMAGE)-arm64 --arch arm64 - docker manifest push $(OPERATOR_IMAGE) -else - @echo "Tagging $(OPERATOR_IMAGE)-amd64 as $(OPERATOR_RELEASE_IMAGE)-amd64" - docker tag $(OPERATOR_IMAGE)-amd64 $(OPERATOR_RELEASE_IMAGE)-amd64 - @echo "Pushing $(OPERATOR_RELEASE_IMAGE)-amd64" - docker push $(OPERATOR_RELEASE_IMAGE)-amd64 - @echo "Tagging $(OPERATOR_IMAGE)-arm64 as $(OPERATOR_RELEASE_IMAGE)-arm64" - docker tag $(OPERATOR_IMAGE)-arm64 $(OPERATOR_RELEASE_IMAGE)-arm64 - @echo "Pushing $(OPERATOR_RELEASE_IMAGE)-arm64" - docker push $(OPERATOR_RELEASE_IMAGE)-arm64 - docker manifest create $(OPERATOR_RELEASE_IMAGE) \ - --amend $(OPERATOR_RELEASE_IMAGE)-amd64 \ - --amend $(OPERATOR_RELEASE_IMAGE)-arm64 - docker manifest annotate $(OPERATOR_RELEASE_IMAGE) $(OPERATOR_RELEASE_IMAGE)-arm64 --arch arm64 - docker manifest push $(OPERATOR_RELEASE_IMAGE) -endif + $(DOCKER_CMD) push $(PUSH_ARGS) $(OPERATOR_IMAGE_AMD) + $(DOCKER_CMD) push $(PUSH_ARGS) $(OPERATOR_IMAGE_ARM) + $(DOCKER_CMD) manifest create $(PUSH_ARGS) $(OPERATOR_IMAGE) \ + --amend $(OPERATOR_IMAGE_AMD) \ + --amend $(OPERATOR_IMAGE_ARM) + $(DOCKER_CMD) manifest push $(PUSH_ARGS) $(OPERATOR_IMAGE) # ---------------------------------------------------------------------------------------------------------------------- # Push the Operator JIB Test Docker images # ---------------------------------------------------------------------------------------------------------------------- .PHONY: push-test-images push-test-images: - docker push $(TEST_APPLICATION_IMAGE) - docker push $(TEST_APPLICATION_IMAGE_CLIENT) - docker push $(TEST_APPLICATION_IMAGE_HELIDON) - docker push $(TEST_APPLICATION_IMAGE_HELIDON_3) - docker push $(TEST_APPLICATION_IMAGE_HELIDON_2) - docker push $(TEST_APPLICATION_IMAGE_SPRING) - docker push $(TEST_APPLICATION_IMAGE_SPRING_FAT) - docker push $(TEST_APPLICATION_IMAGE_SPRING_CNBP) - docker push $(TEST_APPLICATION_IMAGE_SPRING_2) - docker push $(TEST_APPLICATION_IMAGE_SPRING_FAT_2) - docker push $(TEST_APPLICATION_IMAGE_SPRING_CNBP_2) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TEST_APPLICATION_IMAGE) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TEST_APPLICATION_IMAGE_CLIENT) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TEST_APPLICATION_IMAGE_HELIDON) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TEST_APPLICATION_IMAGE_HELIDON_2) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TEST_APPLICATION_IMAGE_HELIDON_3) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TEST_APPLICATION_IMAGE_SPRING) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TEST_APPLICATION_IMAGE_SPRING_CNBP) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TEST_APPLICATION_IMAGE_SPRING_CNBP_2) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TEST_APPLICATION_IMAGE_SPRING_FAT) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TEST_APPLICATION_IMAGE_SPRING_FAT_2) # ---------------------------------------------------------------------------------------------------------------------- # Push the Operator Test images to ttl.sh # ---------------------------------------------------------------------------------------------------------------------- .PHONY: push-ttl-test-images push-ttl-test-images: - docker tag $(TEST_APPLICATION_IMAGE) $(TTL_APPLICATION_IMAGE) - docker push $(TTL_APPLICATION_IMAGE) - docker tag $(TEST_APPLICATION_IMAGE_CLIENT) $(TTL_APPLICATION_IMAGE_CLIENT) - docker push $(TTL_APPLICATION_IMAGE_CLIENT) - docker tag $(TEST_APPLICATION_IMAGE_HELIDON) $(TTL_APPLICATION_IMAGE_HELIDON) - docker push $(TTL_APPLICATION_IMAGE_HELIDON) - docker tag $(TEST_APPLICATION_IMAGE_HELIDON_3) $(TTL_APPLICATION_IMAGE_HELIDON_3) - docker push $(TTL_APPLICATION_IMAGE_HELIDON_3) - docker tag $(TEST_APPLICATION_IMAGE_HELIDON_2) $(TTL_APPLICATION_IMAGE_HELIDON_2) - docker push $(TTL_APPLICATION_IMAGE_HELIDON_2) - docker tag $(TEST_APPLICATION_IMAGE_SPRING) $(TTL_APPLICATION_IMAGE_SPRING) - docker push $(TTL_APPLICATION_IMAGE_SPRING) - docker tag $(TEST_APPLICATION_IMAGE_SPRING_FAT) $(TTL_APPLICATION_IMAGE_SPRING_FAT) - docker push $(TTL_APPLICATION_IMAGE_SPRING_FAT) - docker tag $(TEST_APPLICATION_IMAGE_SPRING_CNBP) $(TTL_APPLICATION_IMAGE_SPRING_CNBP) - docker push $(TTL_APPLICATION_IMAGE_SPRING_CNBP) - docker tag $(TEST_APPLICATION_IMAGE_SPRING_2) $(TTL_APPLICATION_IMAGE_SPRING_2) - docker push $(TTL_APPLICATION_IMAGE_SPRING_2) - docker tag $(TEST_APPLICATION_IMAGE_SPRING_FAT_2) $(TTL_APPLICATION_IMAGE_SPRING_FAT_2) - docker push $(TTL_APPLICATION_IMAGE_SPRING_FAT_2) - docker tag $(TEST_APPLICATION_IMAGE_SPRING_CNBP_2) $(TTL_APPLICATION_IMAGE_SPRING_CNBP_2) - docker push $(TTL_APPLICATION_IMAGE_SPRING_CNBP_2) + $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE) $(TTL_APPLICATION_IMAGE) + $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE) + $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_CLIENT) $(TTL_APPLICATION_IMAGE_CLIENT) + $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_CLIENT) + $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_HELIDON) $(TTL_APPLICATION_IMAGE_HELIDON) + $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_HELIDON) + $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_HELIDON_3) $(TTL_APPLICATION_IMAGE_HELIDON_3) + $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_HELIDON_3) + $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_HELIDON_2) $(TTL_APPLICATION_IMAGE_HELIDON_2) + $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_HELIDON_2) + $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_SPRING) $(TTL_APPLICATION_IMAGE_SPRING) + $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_SPRING) + $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_SPRING_FAT) $(TTL_APPLICATION_IMAGE_SPRING_FAT) + $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_SPRING_FAT) + $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_SPRING_CNBP) $(TTL_APPLICATION_IMAGE_SPRING_CNBP) + $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_SPRING_CNBP) + $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_SPRING_2) $(TTL_APPLICATION_IMAGE_SPRING_2) + $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_SPRING_2) + $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_SPRING_FAT_2) $(TTL_APPLICATION_IMAGE_SPRING_FAT_2) + $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_SPRING_FAT_2) + $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_SPRING_CNBP_2) $(TTL_APPLICATION_IMAGE_SPRING_CNBP_2) + $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_SPRING_CNBP_2) # ---------------------------------------------------------------------------------------------------------------------- # Build the Operator Test images @@ -2279,15 +2365,15 @@ build-compatibility-image: $(BUILD_TARGETS)/java # ---------------------------------------------------------------------------------------------------------------------- .PHONY: push-compatibility-image push-compatibility-image: build-compatibility-image - docker push $(TEST_COMPATIBILITY_IMAGE) + $(DOCKER_CMD) push $(TEST_COMPATIBILITY_IMAGE) # ---------------------------------------------------------------------------------------------------------------------- # Push the Operator JIB Test Docker images to ttl.sh # ---------------------------------------------------------------------------------------------------------------------- .PHONY: push-ttl-compatibility-image push-ttl-compatibility-image: - docker tag $(TEST_COMPATIBILITY_IMAGE) $(TTL_COMPATIBILITY_IMAGE) - docker push $(TTL_COMPATIBILITY_IMAGE) + $(DOCKER_CMD) tag $(TEST_COMPATIBILITY_IMAGE) $(TTL_COMPATIBILITY_IMAGE) + $(DOCKER_CMD) push $(TTL_COMPATIBILITY_IMAGE) # ---------------------------------------------------------------------------------------------------------------------- # Push all of the Docker images @@ -2300,8 +2386,8 @@ push-all-images: push-test-images push-operator-image # ---------------------------------------------------------------------------------------------------------------------- .PHONY: push-ttl-operator-images push-ttl-operator-images: - docker tag $(OPERATOR_IMAGE) $(TTL_OPERATOR_IMAGE) - docker push $(TTL_OPERATOR_IMAGE) + $(DOCKER_CMD) tag $(OPERATOR_IMAGE) $(TTL_OPERATOR_IMAGE) + $(DOCKER_CMD) push $(TTL_OPERATOR_IMAGE) # ---------------------------------------------------------------------------------------------------------------------- # Push all the images to ttl.sh @@ -2493,6 +2579,7 @@ docs: api-doc-gen mkdir -p $(BUILD_OUTPUT)/docs/images/images cp -R docs/images/* build/_output/docs/images/ find examples/ -name \*.png -exec cp {} build/_output/docs/images/images/ \; + tar -C $(BUILD_OUTPUT) -czvf $(BUILD_OUTPUT)/docs.tar.gz ./docs # ---------------------------------------------------------------------------------------------------------------------- # Test the documentation. diff --git a/PROJECT b/PROJECT index 1964ab614..f9d815ef0 100644 --- a/PROJECT +++ b/PROJECT @@ -1,5 +1,6 @@ domain: oracle.com -layout: go.kubebuilder.io/v3 +layout: +- go.kubebuilder.io/v4 projectName: coherence-operator repo: github.com/oracle/coherence-operator resources: diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index cf262b3ef..2620e0880 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -31,6 +31,10 @@ spec: spec: serviceAccountName: service-account terminationGracePeriodSeconds: 10 + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault containers: - name: manager image: controller:latest @@ -91,6 +95,11 @@ spec: initialDelaySeconds: 10 periodSeconds: 10 failureThreshold: 3 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - "ALL" volumes: - name: cert secret: @@ -108,6 +117,19 @@ spec: app.kubernetes.io/instance: coherence-operator-manager app.kubernetes.io/version: "3.4.3" affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/arch + operator: In + values: + - amd64 + - arm64 + - key: kubernetes.io/os + operator: In + values: + - linux podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: diff --git a/config/manifests/bases/coherence-operator.clusterserviceversion.yaml b/config/manifests/bases/coherence-operator.clusterserviceversion.yaml index e8d1a8c5c..c7d1eb25e 100644 --- a/config/manifests/bases/coherence-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/coherence-operator.clusterserviceversion.yaml @@ -2,40 +2,42 @@ apiVersion: operators.coreos.com/v1alpha1 kind: ClusterServiceVersion metadata: annotations: - alm-examples: '[ { "apiVersion": "coherence.oracle.com/v1", "kind": "Coherence", - "metadata": { "name": "coherence-example" }, "spec": { "replicas": 3 } }]' + alm-examples: "[ \n {\n \"apiVersion\": \"coherence.oracle.com/v1\", \n \"kind\": + \"Coherence\",\n \"metadata\": { \n \"name\": \"coherence-example\" + \n }, \n \"spec\": { \n \"replicas\": 3 \n } \n }\n]" capabilities: Full Lifecycle categories: Database - certified: 'false' - createdAt: '' - description: >- - Coherence Operator implements features to assist with deploying and - managing Coherence clusters in a Kubernetes environment. - containerImage: 'ghcr.io/oracle/coherence-operator:3.4.3' - support: '' - repository: 'https://github.com/oracle/coherence-operator' - operators.operatorframework.io/builder: operator-sdk-v1.0.0 - operators.operatorframework.io/project_layout: go.kubebuilder.io/v2 - name: coherence-operator.v3.4.3 - namespace: placeholder + certified: "false" + containerImage: ghcr.io/oracle/coherence-operator:3.4.3 + description: The Oracle Coherence Kubernetes Operator enables easy management + of Coherence clusters in a Kubernetes environment. + operators.operatorframework.io/builder: operator-sdk-v1.39.1 + operators.operatorframework.io/project_layout: go.kubebuilder.io/v4 + repository: https://github.com/oracle/coherence-operator + support: "" + name: coherence-operator.v3.4.2 spec: apiservicedefinitions: {} customresourcedefinitions: owned: - - description: Coherence is the Schema for the Coherence Operator API. + - description: Coherence is the Schema for the Coherence Cluster API. displayName: Coherence kind: Coherence - name: coherence.coherence.oracle.com.oracle.com + name: coherence.coherence.oracle.com + version: v1 + - description: CoherenceJob is the Schema for the Coherence Job API. + displayName: CoherenceJob + kind: CoherenceJob + name: coherencejob.coherence.oracle.com version: v1 description: | - The Coherence Operator implements features to assist with deploying and - managing Coherence clusters in a Kubernetes environment. + The Oracle Coherence Kubernetes Operator enables easy management of Coherence clusters in a Kubernetes environment. ### Installation Guide & Configuration For the complete installation guide and all configuration options please refer to [Coherence Operator Documentation](https://oracle.github.io/coherence-operator/docs/latest/#/about/01_overview). - displayName: Coherence + displayName: Coherence Kubernetes Operator icon: - base64data: iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAAIK2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjYwMDwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+NjU1MzU8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjExMjwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDpkNDMwYzI2Yi05YTNhLTQzN2ItYWZlMy02NWRjYjgyZTY1NTc8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMjAtMDUtMjlUMDc6NTI6MjUtMDQ6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6ZDQzMGMyNmItOWEzYS00MzdiLWFmZTMtNjVkY2I4MmU2NTU3PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPmNyZWF0ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC94bXBNTTpIaXN0b3J5PgogICAgICAgICA8eG1wTU06SW5zdGFuY2VJRD54bXAuaWlkOmQ0MzBjMjZiLTlhM2EtNDM3Yi1hZmUzLTY1ZGNiODJlNjU1NzwveG1wTU06SW5zdGFuY2VJRD4KICAgICAgICAgPHhtcE1NOkRvY3VtZW50SUQ+eG1wLmRpZDpkNDMwYzI2Yi05YTNhLTQzN2ItYWZlMy02NWRjYjgyZTY1NTc8L3ht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 mediatype: image/png @@ -55,14 +57,13 @@ spec: keywords: - coherence links: - - name: Coherence Operator + - name: Coherence Kubernetes Operator url: https://oracle.github.io/coherence-operator/docs/latest + - name: Oracle Coherence + url: https://coherence.community maturity: alpha - minKubeVersion: "1.18" - maintainers: - - name: Jonathan Knight - email: jonathan.knight@oracle.com + minKubeVersion: 1.26.0 provider: - name: Oracle - url: https://oracle.github.io/coherence-operator/docs/latest + name: Oracle Corporation + url: https://github.com/oracle/coherence-operator version: 3.4.3 diff --git a/config/samples/coherence.oracle.com_v1_coherence.yaml b/config/samples/coherence.oracle.com_v1_coherence.yaml index 707ff2b89..1812e4e59 100644 --- a/config/samples/coherence.oracle.com_v1_coherence.yaml +++ b/config/samples/coherence.oracle.com_v1_coherence.yaml @@ -3,4 +3,4 @@ kind: Coherence metadata: name: coherence-sample spec: - replicas: 1 + replicas: 3 diff --git a/hack/coherence-certification.sh b/hack/coherence-certification.sh index abacc8c02..5c995faab 100755 --- a/hack/coherence-certification.sh +++ b/hack/coherence-certification.sh @@ -12,7 +12,7 @@ # by the test suite to install the operator. # # * The Operator image and its test images wil be pushed to an image registry. -# The registry to use should be set using the RELEASE_IMAGE_PREFIX environment +# The registry to use should be set using the OPERATOR_IMAGE_REGISTRY environment # variable. If the registry requires credentials to push to then the # docker login command should already have been executed before this script. # diff --git a/hack/ensure-sdk.sh b/hack/ensure-sdk.sh index 683879bb5..f8418fc51 100755 --- a/hack/ensure-sdk.sh +++ b/hack/ensure-sdk.sh @@ -1,9 +1,11 @@ #!/bin/sh -REQUIRED_VERSION=$1 +REQUIRED_VERSION="$(curl -s https://api.github.com/repos/operator-framework/operator-sdk/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')" OPERATOR_SDK_HOME=$2 UNAME_S=$(uname -s) +UNAME_M=$(uname -m) + OPERATOR_SDK=${OPERATOR_SDK_HOME}/operator-sdk OK=0 @@ -25,12 +27,20 @@ if [ ${OK} != 0 ]; then echo "Operator SDK not found or not correct version" if [ "${UNAME_S}" = "Darwin" ]; then - URL="https://github.com/operator-framework/operator-sdk/releases/download/${REQUIRED_VERSION}/operator-sdk_darwin_amd64" + if [ "${UNAME_S}" = "x86_64" ]; then + URL="https://github.com/operator-framework/operator-sdk/releases/download/${REQUIRED_VERSION}/operator-sdk_darwin_amd64" + else + URL="https://github.com/operator-framework/operator-sdk/releases/download/${REQUIRED_VERSION}/operator-sdk_darwin_arm64" + fi else - URL="https://github.com/operator-framework/operator-sdk/releases/download/${REQUIRED_VERSION}/operator-sdk-linux-amd64" + if [ "${UNAME_S}" = "x86_64" ]; then + URL="https://github.com/operator-framework/operator-sdk/releases/download/${REQUIRED_VERSION}/operator-sdk-linux-amd64" + else + URL="https://github.com/operator-framework/operator-sdk/releases/download/${REQUIRED_VERSION}/operator-sdk-linux-arm64" + fi fi - echo "Downloading Operator SDK ${UNAME_S} version from ${URL}" + echo "Downloading Operator SDK ${UNAME_S}/${UNAME_M} version ${REQUIRED_VERSION} from ${URL}" curl -L ${URL} -o ${OPERATOR_SDK} chmod +x ${OPERATOR_SDK} fi diff --git a/hack/k8s-certification.sh b/hack/k8s-certification.sh index 9882ff0eb..d496aba8c 100755 --- a/hack/k8s-certification.sh +++ b/hack/k8s-certification.sh @@ -12,7 +12,7 @@ # by the test suite to install the operator. # # * The Operator image and its test images wil be pushed to an image registry. -# The registry to use should be set using the RELEASE_IMAGE_PREFIX environment +# The registry to use should be set using the OPERATOR_IMAGE_REGISTRY environment # variable. If the registry requires credentials to push to then the # docker login command should already have been executed before this script. # diff --git a/hack/preflight.yaml b/hack/preflight.yaml new file mode 100644 index 000000000..0e95776a7 --- /dev/null +++ b/hack/preflight.yaml @@ -0,0 +1,64 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: preflight +data: + registry-config.json: | + { + "auths": { + "default-route-openshift-image-registry.apps-crc.testing": { + "auth": "registry-credential-placeholder" + } + } + } +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: preflight +spec: + template: + spec: + imagePullSecrets: + - name: default-dockercfg-l28bp + containers: + - name: preflight + image: "quay.io/opdev/preflight:stable" + command: + - preflight + - check + - container + - --insecure + - image-placeholder + env: + - name: PFLT_LOGLEVEL + value: trace + - name: PFLT_LOGFILE + value: "/artifacts/preflight.log" + - name: PFLT_ARTIFACTS + value: "/artifacts" + - name: PFLT_DOCKERCONFIG + value: /registry-creds/registry-config.json + - name: PFLT_CHANNEL + value: "beta" + volumeMounts: + - name: "outputdir" + mountPath: "/artifacts" + - name: registry-config + mountPath: /registry-creds +# - name: "kubeconfig" +# mountPath: "/creds" + restartPolicy: Never + volumes: + - name: "outputdir" + emptyDir: + medium: "" + - name: registry-config + configMap: + name: preflight + optional: false +# - name: kubeconfig +# secret: +# secretName: test-cluster-kubeconfig +# optional: false + backoffLimit: 2 diff --git a/hack/setup-podman.sh b/hack/setup-podman.sh new file mode 100644 index 000000000..4ab8ad680 --- /dev/null +++ b/hack/setup-podman.sh @@ -0,0 +1,21 @@ +# +# Copyright (c) 2020, 2025, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at +# http://oss.oracle.com/licenses/upl. +# + +#!/usr/bin/env bash + +# -------------------------------------------------------------------- +# This script exports various environment variables so that +# Make targets will be executed using Podman and OpenShift. +# -------------------------------------------------------------------- + +export DOCKER_CMD=podman +export PUSH_ARGS=--tls-verify=false +export REGISTRY=$(oc get route/default-route -n openshift-image-registry -o=jsonpath='{.spec.host}') +export OPERATOR_IMAGE_REGISTRY=${REGISTRY}/oracle +export PREFLIGHT_REGISTRY_CRED=$(echo -n bogus:$(oc whoami -t) | base64) + +podman login -u bogus -p $(oc whoami -t) --tls-verify=false ${REGISTRY} + diff --git a/helm-charts/coherence-operator/Chart.yaml b/helm-charts/coherence-operator/Chart.yaml index 5275506b4..ff097d7d1 100644 --- a/helm-charts/coherence-operator/Chart.yaml +++ b/helm-charts/coherence-operator/Chart.yaml @@ -4,10 +4,11 @@ name: coherence-operator description: A Kubernetes Operator for Coherence -apiVersion: v1 +apiVersion: v2 version: ${VERSION} appVersion: ${VERSION} home: https://github.com/oracle/coherence-operator sources: - https://github.com/oracle/coherence-operator icon: "https://docs.oracle.com/en/dcommon/img/oracle-doc-logo.png" +kubeVersion: ">=1.26" diff --git a/helm-charts/coherence-operator/templates/deployment.yaml b/helm-charts/coherence-operator/templates/deployment.yaml index 9cedc86b9..04dec6ff4 100644 --- a/helm-charts/coherence-operator/templates/deployment.yaml +++ b/helm-charts/coherence-operator/templates/deployment.yaml @@ -274,9 +274,9 @@ spec: tolerations: {{ toYaml .Values.tolerations | indent 8 }} {{- end }} -{{- if .Values.affinity }} +{{- if .Values.topologySpreadConstraints }} topologySpreadConstraints: -{{ toYaml .Values.affinity | indent 8 }} +{{ toYaml .Values.topologySpreadConstraints | indent 8 }} {{- else }} topologySpreadConstraints: - maxSkew: 1 @@ -294,6 +294,19 @@ spec: {{ toYaml .Values.affinity | indent 8 }} {{- else }} affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/arch + operator: In + values: + - amd64 + - arm64 + - key: kubernetes.io/os + operator: In + values: + - linux podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: diff --git a/java/operator-test-helidon/pom.xml b/java/operator-test-helidon/pom.xml index 50a2d775f..eece76f42 100644 --- a/java/operator-test-helidon/pom.xml +++ b/java/operator-test-helidon/pom.xml @@ -85,7 +85,7 @@ ${version.plugin.jib} - docker://${coherence.test.base.image.21} + ${coherence.test.base.image.21} io.helidon.microprofile.cdi.Main diff --git a/java/operator-test-spring/pom.xml b/java/operator-test-spring/pom.xml index 31f3176b2..cae5357ec 100644 --- a/java/operator-test-spring/pom.xml +++ b/java/operator-test-spring/pom.xml @@ -103,7 +103,7 @@ ${version.plugin.jib} - docker://${coherence.test.base.image.21} + ${coherence.test.base.image.21} true diff --git a/java/operator-test/pom.xml b/java/operator-test/pom.xml index 7f7615319..5314652c2 100644 --- a/java/operator-test/pom.xml +++ b/java/operator-test/pom.xml @@ -59,7 +59,7 @@ ${version.plugin.jib} - docker://${coherence.test.base.image} + ${coherence.test.base.image} com.oracle.coherence.k8s.testing.RestServer diff --git a/java/pom.xml b/java/pom.xml index c57d9047e..1227ac408 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -273,7 +273,7 @@ ${version.plugin.jib} - docker://${coherence.test.base.image} + ${coherence.test.base.image} OCI From de3526b43ea37a9fe939861b6edff467e236ebce Mon Sep 17 00:00:00 2001 From: Jonathan Knight Date: Fri, 21 Feb 2025 15:16:19 +0300 Subject: [PATCH 04/11] Fix unit test --- pkg/runner/runner_spring_test.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/runner/runner_spring_test.go b/pkg/runner/runner_spring_test.go index 58832eb63..e03c0f6c3 100644 --- a/pkg/runner/runner_spring_test.go +++ b/pkg/runner/runner_spring_test.go @@ -161,6 +161,8 @@ func TestSpringBootFatJarConsole(t *testing.T) { expectedCommand := GetJavaCommand() expectedArgs := GetMinimalExpectedSpringBootFatJarArgsForRole(jar, ConsoleMain, "") + expectedArgs = append(expectedArgs, "-Dcoherence.localport.adjust=true", + "-Dcoherence.management.http.enabled=false", "-Dcoherence.metrics.http.enabled=false") e, err := ExecuteWithArgsAndNewViper(env, args) g.Expect(err).NotTo(HaveOccurred()) @@ -192,7 +194,10 @@ func TestSpringBootFatJarConsoleWithArgs(t *testing.T) { env := EnvVarsFromDeployment(d) expectedCommand := GetJavaCommand() - expectedArgs := append(GetMinimalExpectedSpringBootFatJarArgsForRole(jar, ConsoleMain, ""), "foo", "bar") + expectedArgs := GetMinimalExpectedSpringBootFatJarArgsForRole(jar, ConsoleMain, "") + expectedArgs = append(expectedArgs, "-Dcoherence.localport.adjust=true", + "-Dcoherence.management.http.enabled=false", "-Dcoherence.metrics.http.enabled=false", + "foo", "bar") e, err := ExecuteWithArgsAndNewViper(env, args) g.Expect(err).NotTo(HaveOccurred()) From 7108dbbb5fdc8d35c5c32618b2acfd8da101cfb9 Mon Sep 17 00:00:00 2001 From: Jonathan Knight Date: Tue, 25 Feb 2025 19:40:54 +0300 Subject: [PATCH 05/11] Spring console fixes --- Makefile | 53 +++++--- config/manager/manager.yaml | 2 + ...erence-operator.clusterserviceversion.yaml | 65 ++++++---- hack/setup-podman.sh | 5 + .../CoherenceOperatorLifecycleListener.java | 122 ++++++++++++------ java/operator-compatibility/image-build.sh | 2 +- java/operator-compatibility/pom.xml | 1 + java/operator-test-helidon-2/pom.xml | 4 + java/operator-test-helidon-3/pom.xml | 4 + java/operator-test-helidon/pom.xml | 4 + java/operator-test-spring-2/pom.xml | 4 + java/operator-test-spring/pom.xml | 4 + java/operator-test/pom.xml | 4 + runner/main.go | 4 +- 14 files changed, 189 insertions(+), 89 deletions(-) diff --git a/Makefile b/Makefile index 09f6d4a48..c9ea2ba20 100644 --- a/Makefile +++ b/Makefile @@ -61,6 +61,10 @@ TEST_COHERENCE_IMAGE ?= $(COHERENCE_IMAGE) TEST_COHERENCE_VERSION ?= $(COHERENCE_VERSION) TEST_COHERENCE_GID ?= com.oracle.coherence.ce +# The minimum certified OpenShift version the Operator runs on +OPENSHIFT_MIN_VERSION := v4.15 +OPENSHIFT_COMPONENT_PID := 67b738ef88736e8a179ac976 + # The current working directory CURRDIR := $(shell pwd) @@ -340,13 +344,15 @@ SHELL = /usr/bin/env bash -o pipefail # Capture the Git commit to add to the build information that is then embedded in the Go binary # ---------------------------------------------------------------------------------------------------------------------- GITCOMMIT ?= $(shell git rev-list -1 HEAD) +GITBRANCH ?= $(shell git branch --show-current) GITREPO := https://github.com/oracle/coherence-operator.git SOURCE_DATE_EPOCH := $(shell git show -s --format=format:%ct HEAD) DATE_FMT := "%Y-%m-%dT%H:%M:%SZ" -BUILD_DATE := $(shell date -u -d "@$SOURCE_DATE_EPOCH" "+${DATE_FMT}" 2>/dev/null || date -u -r "${SOURCE_DATE_EPOCH}" "+${DATE_FMT}" 2>/dev/null || date -u "+${DATE_FMT}") +#BUILD_DATE := $(shell date -u -d "@$SOURCE_DATE_EPOCH" "+${DATE_FMT}" 2>/dev/null || date -u -r "${SOURCE_DATE_EPOCH}" "+${DATE_FMT}" 2>/dev/null || date -u "+${DATE_FMT}") +BUILD_DATE := $(shell date -u "+${DATE_FMT}") BUILD_USER := $(shell whoami) -LDFLAGS = -X main.Version=$(VERSION) -X main.Commit=$(GITCOMMIT) -X main.Date=$(BUILD_DATE) -X main.Author=$(BUILD_USER) +LDFLAGS = -X main.Version=$(VERSION) -X main.Commit=$(GITCOMMIT) -X main.Branch=$(GITBRANCH) -X main.Date=$(BUILD_DATE) -X main.Author=$(BUILD_USER) GOS = $(shell find . -type f -name "*.go" ! -name "*_test.go") HELM_FILES = $(shell find helm-charts/coherence-operator -type f) API_GO_FILES = $(shell find . -type f -name "*.go" ! -name "*_test.go" ! -name "zz*.go") @@ -460,7 +466,9 @@ $(BUILD_PROPS): clean: ## Cleans the build -rm -rf $(BUILD_OUTPUT) || true -rm -rf $(BUILD_BIN) || true + -rm -rf artifacts || true -rm -rf bundle || true + -rm bundle.Dockerfile || true rm config/crd/bases/*.yaml || true rm -rf config/crd-small || true rm pkg/data/zz_generated_*.go || true @@ -895,6 +903,13 @@ bundle: $(BUILD_PROPS) ensure-sdk $(TOOLS_BIN)/kustomize $(BUILD_TARGETS)/manife $(OPERATOR_SDK) generate kustomize manifests cd config/manager && $(KUSTOMIZE) edit set image controller=$(OPERATOR_IMAGE) $(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) + @echo "" >> ./bundle/metadata/annotations.yaml + @echo " # OpenShift annotations" >> ./bundle/metadata/annotations.yaml + @echo " com.redhat.openshift.versions: $(OPENSHIFT_MIN_VERSION)" >> ./bundle/metadata/annotations.yaml + @echo "" >> bundle.Dockerfile + @echo "# OpenShift labels" >> bundle.Dockerfile + @echo "LABEL com.redhat.openshift.versions=$(OPENSHIFT_MIN_VERSION)" >> bundle.Dockerfile + @echo "cert_project_id: $(OPENSHIFT_COMPONENT_PID)" > bundle/ci.yaml $(OPERATOR_SDK) bundle validate ./bundle $(OPERATOR_SDK) bundle validate ./bundle --select-optional suite=operatorframework --optional-values=k8s-version=1.26 $(OPERATOR_SDK) bundle validate ./bundle --select-optional name=operatorhubv2 --optional-values=k8s-version=1.26 @@ -952,7 +967,7 @@ catalog-build: opm ## Build a catalog image. # Push the catalog image. .PHONY: catalog-push catalog-push: ## Push a catalog image. - $(DOCKER_CMD) push $(CATALOG_IMAGE) + $(DOCKER_CMD) push $(PUSH_ARGS) $(CATALOG_IMAGE) .PHONY: scorecard scorecard: $(BUILD_PROPS) ensure-sdk bundle ## Run the Operator SDK scorecard tests. @@ -1037,9 +1052,6 @@ jk: $(BUILD_PREFLIGHT)/preflight.yaml # Generate the preflight job yaml $(BUILD_PREFLIGHT)/preflight.yaml: hack/preflight.yaml -#ifeq ($(PREFLIGHT_REGISTRY_CRED),) -# $(error $(n)The PREFLIGHT_REGISTRY_CRED variable must be specified to run preflight$(n)Typically using the command$(n)$(n) export PREFLIGHT_REGISTRY_CRED=$$(echo -n bogus:$$(oc whoami -t) | base64)$(n)$(n)) -#endif cp hack/preflight.yaml $(BUILD_PREFLIGHT)/preflight.yaml $(SED) -e 's^image-placeholder^$(OPERATOR_IMAGE)^g' $(BUILD_PREFLIGHT)/preflight.yaml $(SED) -e 's/registry-credential-placeholder/$(PREFLIGHT_REGISTRY_CRED)/g' $(BUILD_PREFLIGHT)/preflight.yaml @@ -2299,6 +2311,7 @@ PUSH_ARGS ?= push-operator-image: $(BUILD_TARGETS)/build-operator $(DOCKER_CMD) push $(PUSH_ARGS) $(OPERATOR_IMAGE_AMD) $(DOCKER_CMD) push $(PUSH_ARGS) $(OPERATOR_IMAGE_ARM) + $(DOCKER_CMD) rmi $(OPERATOR_IMAGE) || true $(DOCKER_CMD) manifest create $(PUSH_ARGS) $(OPERATOR_IMAGE) \ --amend $(OPERATOR_IMAGE_AMD) \ --amend $(OPERATOR_IMAGE_ARM) @@ -2326,27 +2339,27 @@ push-test-images: .PHONY: push-ttl-test-images push-ttl-test-images: $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE) $(TTL_APPLICATION_IMAGE) - $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TTL_APPLICATION_IMAGE) $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_CLIENT) $(TTL_APPLICATION_IMAGE_CLIENT) - $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_CLIENT) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TTL_APPLICATION_IMAGE_CLIENT) $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_HELIDON) $(TTL_APPLICATION_IMAGE_HELIDON) - $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_HELIDON) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TTL_APPLICATION_IMAGE_HELIDON) $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_HELIDON_3) $(TTL_APPLICATION_IMAGE_HELIDON_3) - $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_HELIDON_3) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TTL_APPLICATION_IMAGE_HELIDON_3) $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_HELIDON_2) $(TTL_APPLICATION_IMAGE_HELIDON_2) - $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_HELIDON_2) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TTL_APPLICATION_IMAGE_HELIDON_2) $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_SPRING) $(TTL_APPLICATION_IMAGE_SPRING) - $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_SPRING) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TTL_APPLICATION_IMAGE_SPRING) $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_SPRING_FAT) $(TTL_APPLICATION_IMAGE_SPRING_FAT) - $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_SPRING_FAT) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TTL_APPLICATION_IMAGE_SPRING_FAT) $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_SPRING_CNBP) $(TTL_APPLICATION_IMAGE_SPRING_CNBP) - $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_SPRING_CNBP) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TTL_APPLICATION_IMAGE_SPRING_CNBP) $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_SPRING_2) $(TTL_APPLICATION_IMAGE_SPRING_2) - $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_SPRING_2) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TTL_APPLICATION_IMAGE_SPRING_2) $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_SPRING_FAT_2) $(TTL_APPLICATION_IMAGE_SPRING_FAT_2) - $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_SPRING_FAT_2) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TTL_APPLICATION_IMAGE_SPRING_FAT_2) $(DOCKER_CMD) tag $(TEST_APPLICATION_IMAGE_SPRING_CNBP_2) $(TTL_APPLICATION_IMAGE_SPRING_CNBP_2) - $(DOCKER_CMD) push $(TTL_APPLICATION_IMAGE_SPRING_CNBP_2) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TTL_APPLICATION_IMAGE_SPRING_CNBP_2) # ---------------------------------------------------------------------------------------------------------------------- # Build the Operator Test images @@ -2365,7 +2378,7 @@ build-compatibility-image: $(BUILD_TARGETS)/java # ---------------------------------------------------------------------------------------------------------------------- .PHONY: push-compatibility-image push-compatibility-image: build-compatibility-image - $(DOCKER_CMD) push $(TEST_COMPATIBILITY_IMAGE) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TEST_COMPATIBILITY_IMAGE) # ---------------------------------------------------------------------------------------------------------------------- # Push the Operator JIB Test Docker images to ttl.sh @@ -2373,7 +2386,7 @@ push-compatibility-image: build-compatibility-image .PHONY: push-ttl-compatibility-image push-ttl-compatibility-image: $(DOCKER_CMD) tag $(TEST_COMPATIBILITY_IMAGE) $(TTL_COMPATIBILITY_IMAGE) - $(DOCKER_CMD) push $(TTL_COMPATIBILITY_IMAGE) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TTL_COMPATIBILITY_IMAGE) # ---------------------------------------------------------------------------------------------------------------------- # Push all of the Docker images @@ -2387,7 +2400,7 @@ push-all-images: push-test-images push-operator-image .PHONY: push-ttl-operator-images push-ttl-operator-images: $(DOCKER_CMD) tag $(OPERATOR_IMAGE) $(TTL_OPERATOR_IMAGE) - $(DOCKER_CMD) push $(TTL_OPERATOR_IMAGE) + $(DOCKER_CMD) push $(PUSH_ARGS) $(TTL_OPERATOR_IMAGE) # ---------------------------------------------------------------------------------------------------------------------- # Push all the images to ttl.sh diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 2620e0880..0e97ee782 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -28,6 +28,8 @@ spec: version: "3.4.3" app.kubernetes.io/component: manager app.kubernetes.io/part-of: coherence-operator + annotations: + alpha.image.policy.openshift.io/resolve-names: '*' spec: serviceAccountName: service-account terminationGracePeriodSeconds: 10 diff --git a/config/manifests/bases/coherence-operator.clusterserviceversion.yaml b/config/manifests/bases/coherence-operator.clusterserviceversion.yaml index c7d1eb25e..4cc4594db 100644 --- a/config/manifests/bases/coherence-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/coherence-operator.clusterserviceversion.yaml @@ -11,25 +11,36 @@ metadata: containerImage: ghcr.io/oracle/coherence-operator:3.4.3 description: The Oracle Coherence Kubernetes Operator enables easy management of Coherence clusters in a Kubernetes environment. + features.operators.openshift.io/cnf: "false" + features.operators.openshift.io/cni: "false" + features.operators.openshift.io/csi: "false" + features.operators.openshift.io/disconnected: "true" + features.operators.openshift.io/fips-compliant: "true" + features.operators.openshift.io/proxy-aware: "false" + features.operators.openshift.io/tls-profiles: "false" + features.operators.openshift.io/token-auth-aws: "false" + features.operators.openshift.io/token-auth-azure: "false" + features.operators.openshift.io/token-auth-gcp: "false" + operators.openshift.io/infrastructure-features: '["disconnected"]' operators.operatorframework.io/builder: operator-sdk-v1.39.1 operators.operatorframework.io/project_layout: go.kubebuilder.io/v4 repository: https://github.com/oracle/coherence-operator - support: "" + support: Oracle Corporation name: coherence-operator.v3.4.2 spec: apiservicedefinitions: {} customresourcedefinitions: owned: - - description: Coherence is the Schema for the Coherence Cluster API. - displayName: Coherence - kind: Coherence - name: coherence.coherence.oracle.com - version: v1 - - description: CoherenceJob is the Schema for the Coherence Job API. - displayName: CoherenceJob - kind: CoherenceJob - name: coherencejob.coherence.oracle.com - version: v1 + - description: Coherence is the Schema for the Coherence Cluster API. + displayName: Coherence + kind: Coherence + name: coherence.coherence.oracle.com + version: v1 + - description: CoherenceJob is the Schema for the Coherence Job API. + displayName: CoherenceJob + kind: CoherenceJob + name: coherencejob.coherence.oracle.com + version: v1 description: | The Oracle Coherence Kubernetes Operator enables easy management of Coherence clusters in a Kubernetes environment. @@ -39,31 +50,31 @@ spec: [Coherence Operator Documentation](https://oracle.github.io/coherence-operator/docs/latest/#/about/01_overview). displayName: Coherence Kubernetes Operator icon: - - base64data: iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAAIK2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjYwMDwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+NjU1MzU8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjExMjwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDpkNDMwYzI2Yi05YTNhLTQzN2ItYWZlMy02NWRjYjgyZTY1NTc8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMjAtMDUtMjlUMDc6NTI6MjUtMDQ6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6ZDQzMGMyNmItOWEzYS00MzdiLWFmZTMtNjVkY2I4MmU2NTU3PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPmNyZWF0ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC94bXBNTTpIaXN0b3J5PgogICAgICAgICA8eG1wTU06SW5zdGFuY2VJRD54bXAuaWlkOmQ0MzBjMjZiLTlhM2EtNDM3Yi1hZmUzLTY1ZGNiODJlNjU1NzwveG1wTU06SW5zdGFuY2VJRD4KICAgICAgICAgPHhtcE1NOkRvY3VtZW50SUQ+eG1wLmRpZDpkNDMwYzI2Yi05YTNhLTQzN2ItYWZlMy02NWRjYjgyZTY1NTc8L3ht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 - mediatype: image/png + - base64data: iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAAIK2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjYwMDwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+NjU1MzU8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjExMjwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDpkNDMwYzI2Yi05YTNhLTQzN2ItYWZlMy02NWRjYjgyZTY1NTc8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMjAtMDUtMjlUMDc6NTI6MjUtMDQ6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6ZDQzMGMyNmItOWEzYS00MzdiLWFmZTMtNjVkY2I4MmU2NTU3PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPmNyZWF0ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC94bXBNTTpIaXN0b3J5PgogICAgICAgICA8eG1wTU06SW5zdGFuY2VJRD54bXAuaWlkOmQ0MzBjMjZiLTlhM2EtNDM3Yi1hZmUzLTY1ZGNiODJlNjU1NzwveG1wTU06SW5zdGFuY2VJRD4KICAgICAgICAgPHhtcE1NOkRvY3VtZW50SUQ+eG1wLmRpZDpkNDMwYzI2Yi05YTNhLTQzN2ItYWZlMy02NWRjYjgyZTY1NTc8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXA6Q3JlYXRlRGF0ZT4yMDIwLTA1LTI5VDA3OjUyOjI1LTA0OjAwPC94bXA6Q3JlYXRlRGF0ZT4KICAgICAgICAgPHhtcDpNZXRhZGF0YURhdGU+MjAyMC0wNi0wM1QwNDoyNzoyMC0wNDowMDwveG1wOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPHhtcDpNb2RpZnlEYXRlPjIwMjAtMDYtMDNUMDQ6Mjc6MjAtMDQ6MDA8L3htcDpNb2RpZnlEYXRlPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE1IChNYWNpbnRvc2gpPC94bXA6Q3JlYXRvclRvb2w+CiAgICAgICAgIDxwaG90b3Nob3A6Q29sb3JNb2RlPjM8L3Bob3Rvc2hvcDpDb2xvck1vZGU+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgoVhnKPAAAMyklEQVR4Ae1dW3LbOBa9kGRXzVerVzDyCsb5nYo78graWcHYK0i8AscrsHsFdlZg9wrMHqXmN95BNDvQfPVUJAp9DkjYlE2RIAmCTJVUZfMB4AK4h7gvAKTI7rfjwI4DOw7sOLDjQD0OqHrFui/1p0wnw0F8obScoDXjpEX6UWv1277MbrtvYb0W/HCAaJmOV7L+KEp/QJdTIF52Xj+KlvM9+RK9TOn79Q8FyEqOTtZKrtDoiSNj71d6eP43ieaO+TvP9kMA8l3+eajU8ArcmtbimFaXIxlcK4kWtcoHLNRrQCieloP4CnritClPtMgcYuyy7/qlt4B8l6OPSskFgNiiJ2pDFInWl33VL70DZClvp1qpGzRsUpvlDgW1ktt4Pbzsm37pDSA0Y0cqvgEvpw789JVlITCT9+Tfn3wRbEqnc0CMGQt/AvL9Y9PO1C1P/TKAmTyS2X1dGr7KdQoI9MQp9AStJ996oi5/Iq3j8335z2NdAk3LdQII9YQYINRh0w6wPPUBLLEJTqf4a/5Tcj2CfunCTA4KSKonOCJOmnPNUIjg+J1Zxex5xC10YiZfe2qrE5kggLiFO5zaazIVyfxMXTSZG/9Yl9L6LJSZ3DogfGohni5Q0aQxd0ScraK2R6OHvuSSaA2QRE8oPqXT3Jor3qSe2FsPz6vKde9+TcthGO+A+Ax3pJh58aw9e/7UL7DG/If5vQKylF8+FYfF3YcFZbfv2JN/n8d/mN8bIN/V0TcQm7izvCBny2KhcfT4ZdPRXl/e/uAl7brXnsDg/MUBO1dVV1RpNx2/PT07hu/y3ozEKoXz8ir9Lu92nXveAKlT+XMZDn19DCa9tz7Fc1p7ZwyV7OvZATzLS9SyaK8md8pdA0LleLanv7wJZefnsYYjEiPzDS25vPSQ97oDhOEJiKc2LJU6DOTI3F/PzjhSUT6qQ8NHmS4AYbjjYG89q+xT+OhwGQ2OVOoXjlzkDS7GggGSmLFGTxyH1BNlAGxL58jlCE71y7Zs3u+HAIThjksqzy71RB3O0dJL9csByt/XoVG1TKuAUEnyKfNlo1ftnK/8HNG0AKlfvJjJBQ1rCxBO9LyhkmzTnyjoVytJHOEc6QyboIJW9ItXQPj0JGbs7LjLWbdW0MgQhX4xFqLAUszc7tcp41iMFfWrVe23hmEYE8Nrv6pdDTsO7DgAKdjgZ2blZDVp05xNpmRXhyKDqQz0TwjJ45w/DfGYu0higcRHk0Nh+nWt/qtFz/dkeN+2gcHF4E2XEtUCZGNewWPomUwkyEOJwXx5B+ZP0cAJ73v4IW4Wt2psLNXRAwybSZM1XqOqHeUc+UrFV2AWnlA/vxSEE6X0v0TiQ0MVPfP8G2MF/QPa/bNnuhvk+ADB/7pbyhFN/8prvJwBeV5LZUXGRjtqXRggzC6o+DQhUGvAVql7zH5YEcuRvpSYi/V+BRFEFDSWlX6JqhAsyDvFA/AVE3eV1gKU+iFkGobinSj1sEVmF7QpP8kwYnB0hbW83zBJdJqfq/27K7V6SFdOTlHbCftoVsl4rJr9g0T5xjl9F7KFgJAImPbVNNaFmkMeY7eTZkdreVcymrOZVMC5D1iyBcKhJ5WyQFzKFae52f+ikoWApEN5XESgShqfPspxj4q6SvXgv1zbSLPOt9CQRSbViLrnJm0lIzwI23/OOmQ7CbeUVAfduOUuzgV9P0fn5qJg3q7V//Jy64H+O8TFxKYhpPMZcahbe60EO3btReZI2pnL4KdBADFmsorv6vTOMAgOhKzlD1hgjxsxsjyO2krW9iT/SH8BD8njK7GF9bz5JcLcDQKIsWQqbDkwIGj5LYYzZ0RMEeMb8GmkR8fpFut3IGOsrP3UyrKmOO+HcCptN4IAkvgXEDIlPwJBp2ov0MaZ1HP/BANj45eIVzOijf5cSXz1p56+sfpnI7Pni0Kl7q+u3BDHBnmCsYeVH01DDxtE61683kQ05lsj6pKrUi4QIOVNUlp9bjvWVN4Km+P1A5Q1EGyuNo6hAFmUNZ5WUVmegOn3r+rSCkZF+79QgERlXaFH69tLLqtzWzpiUJcUoZn0iG+CyFy3dhoGEMSIXHoAR/Smq9m3JUI5CBFpRmzZ1mSJKRY1YG2AWQcc6LUcQQAxATvX+WelL5bq7Vdj6big6CGPiTM9h3IYFOQ+SGG7N/weD3WVkQgCiOkcVipyWVBZg5J0KFUG+gZHN/QH3Mq450qivHhjRLoGQIky5m2GwjRzHvQ0GCDsFZcFuYMCHxp6hRFhihFfIyaJGqweCDijvQko62iD666jeaOQn4uggLDJdkHzC6VZ1pupGTEmWnr00T7ZZYWy6YyycrSthNPB1qxVh7w2IpWLrDH7iZjXOdcdZ8uGPA8OCDtnZHOy4OwMc+OPrh2Grz9hGNvML0CclYWySZf6gQBysmio4oeRjFCfrVM/JtdJm7jCkmuuXNvTRr5OALEd4YJm7g2hJZOKsoVNKzmOKc7IZIqzPHOZIo5/BJCxNNC7x7lZ6MAYFmYHj3nsjzOa9DhILKuEuWIsmbWc4Uk+B/NOEPv68CxWykpjIYSSKUDBCzHV55UMbhlz4iueaLou9dtjEzDUWGUIOclfCkJkLnr2r9MR8pIXZFTdUUNxBivggkYArTOFty+QvtEPLyvq8XWvAMnyiaOGBgBXz0PRkrlRNr3onOJMYEXRn6E4q2MEFNFvM623gNhOP4+a2TF3XkHeXLtbaOoQ4uyGRgA98TZ8GttOX8feA8Knm8qZR1pJsta/UzdgFLwHE+4dGTGG/uCCDa8+jWPdlbL1HhBjIVH8wFIiEFYncN6Em2gg0n6m7/Bsypb2f5qIM1pnxStASim1kKG3gJglM3AEMX16S4fNHHMYkIq0a2s+U6Qhm4v5DOtsmGsy51QT7FbvALEhEuMzpH4DHbbUVC1kDA0BetkYORw1LoYAHEZxcjALK/aY2CtAkpfXUDxhuScZ2yCEkZjPM+MAgl9REc8wUi6K0kOm9cIxtB3WsrpXGsEMGT7ae02PSZxKIjPylOJSpHEOzZOce53c6hUg6dyDNzCyHCUwWk8PGOGFr36YTevTea9EFgOBnLXLi035YJrRQ3rwuw9abdHoFSDo5IJ/WOY5pxNnFbyvzhugk++ObJCsMkezUbCFi56JrBlMXLk1oQ44cRAt4+/6iK/SuyY4DJW7WFuWTwTVYTfWgu+At2W6PvYKkG3MoCiDf8Ew+hx64A0/YcG8fCnm/6GkR7I+fSqr9D9wPkZ4ZaIknpj7uMj/8RNJa7z3dzbPTw9/tzkgav0rQtyR9aB9dIGjgEs3R9hQytB5shIFGwjAaM7wIcx+ynpw/nm0xXJC3q0/4DNnqB7W3HWVEbeVIBLMQyPNd5c1B4QWi5KHqlu3ijrHtHQd7ZznXBO11DH0SxzFsr+AGDL3Y2y+GUk8Zp7yH2YJlYoUVtH7XDtMUerz8xoeAElYwZA3oqonS/2L988/pE/x9RPTtRzY85U+wnsT881YboemgfA0ereKLkvN/Uj9hGAlRedJ0Wh0p5jkLKQFE5SO1ElVohQJTbYGV60vZH4aHOkWhota9WLq+OkBySFQaPYiHlTLZgfKE5iSd5zv/hHmIHL4knuLZvOS+yMxM5mbofzmwi6q2Ja1cISwEGfdGnu2iMB29fmHbR2vcp9hesS7KJ6mVcq9yuvwkoVSQMycgRre8al/VUG1G3wD6SV9imrFustN8eTtK3FKbs2atJLulALC8kZuevssEd/R2/+vcNKMRWieosnRitvKaWyVc//OlRMgtqrUsrjB9dTea3Ds5Vc4fZqxDMlU/RJcJUAs82t8AtUWfX2EXO3DVzizZuzrRla9U18K1ALENi+ZUCr6SLDNWXzU3ByT6Jfb4pz+UzNm7AdQbyyeOL/PybG6LW0ECCv1qfhALsISz8siO71uR/PK9XGkNwbEdtSbaQiClL11vqZj21J29NlW1LXxYbKyusvSvQFiK6LzhNjWBQhP7L2ax0rWiUsdPq1FilkuV/U9mr0DQsb4lMvsuI8wjE8ztk1/qhVA7NPq13IRzIlXf0ObmXXEXErjaAM7FSDi0CogFpgumNKHh8H2v8oxCCC2QdQv8H4ZE/JhXuaGYfooLm3/XY5BAWGDMgy7cGlgUR7ql1gPnz5/4dHL9m5QFPUjm1YYfs9m9HXOyabMJyCi+nT1I62c7Bt6zCIITM3Wp5mY3Pz8UVdfdAg+Ql4yq8ZTzahxoTdcU39EIZ3Sl3yw150DYhviZJZWtHJcjAmKva7CNrbv2WNvAGGjqF+2zD808oa3GhM9CWxmAenlOUMbZrsz9oeYp9xDKxOwn14wc0ex5oHsjsSOAzsO7Diw48COA73hwF/JV5eOHd1hjQAAAABJRU5ErkJggg== + mediatype: image/png install: spec: deployments: null strategy: "" installModes: - - supported: true - type: OwnNamespace - - supported: true - type: SingleNamespace - - supported: true - type: MultiNamespace - - supported: true - type: AllNamespaces + - supported: true + type: OwnNamespace + - supported: true + type: SingleNamespace + - supported: true + type: MultiNamespace + - supported: true + type: AllNamespaces keywords: - - coherence + - coherence links: - - name: Coherence Kubernetes Operator - url: https://oracle.github.io/coherence-operator/docs/latest - - name: Oracle Coherence - url: https://coherence.community + - name: Coherence Kubernetes Operator + url: https://oracle.github.io/coherence-operator/docs/latest + - name: Oracle Coherence + url: https://coherence.community maturity: alpha minKubeVersion: 1.26.0 provider: name: Oracle Corporation url: https://github.com/oracle/coherence-operator - version: 3.4.3 + version: 3.4.3 \ No newline at end of file diff --git a/hack/setup-podman.sh b/hack/setup-podman.sh index 4ab8ad680..1d2ae5ed1 100644 --- a/hack/setup-podman.sh +++ b/hack/setup-podman.sh @@ -18,4 +18,9 @@ export OPERATOR_IMAGE_REGISTRY=${REGISTRY}/oracle export PREFLIGHT_REGISTRY_CRED=$(echo -n bogus:$(oc whoami -t) | base64) podman login -u bogus -p $(oc whoami -t) --tls-verify=false ${REGISTRY} +podman login -u bogus -p $(oc whoami -t) --tls-verify=false ${OPERATOR_IMAGE_REGISTRY} +#oc new-project oracle || true +#oc -n oracle create is coherence-operator || true +# Allow anyone to pull oracle images +#oc adm policy add-role-to-group system:image-puller system:authenticated --namespace=oracle \ No newline at end of file diff --git a/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceOperatorLifecycleListener.java b/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceOperatorLifecycleListener.java index cfa27832c..39ce1930b 100644 --- a/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceOperatorLifecycleListener.java +++ b/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceOperatorLifecycleListener.java @@ -157,7 +157,7 @@ public void preStart(Context context) { context.getConfigurableCacheFactory().getInterceptorRegistry().registerEventInterceptor(this); } catch (Throwable t) { - LOGGER.error("Failed to initialise the Coherence Operator", t); + LOGGER.error("CoherenceOperator: Failed to initialise the Coherence Operator", t); } } @@ -281,59 +281,101 @@ void initCohCtl() { 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"); - File fileHome = new File(home); String connectionType = "http"; - if (!fileHome.exists() || !fileHome.isDirectory()) { - LOGGER.info("CoherenceOperator: user home \"" + home - + "\" does not exist, creating default cohctl config at /coherence-operator/utils"); - home = "/coherence-operator/utils"; - fileHome = new File(home); + + // If COHCTL_HOME is set use that for the config location + String cohCtlHome = System.getenv("COHCTL_HOME"); + if (cohCtlHome == null || !cohCtlHome.isEmpty()) { + // Try corresponding system property + cohCtlHome = Config.getProperty("cohctl.home"); } - if (!fileHome.exists() || !fileHome.isDirectory()) { - LOGGER.error("CoherenceOperator: Cannot create cohctl config, directory " + home + " does not exist"); + // If we have a COHCTL_HOME env var or property try to create the config there + if (cohCtlHome != null && !cohCtlHome.isEmpty() && tryCreateConfig(new File(cohCtlHome), connectionType, protocol, port, clusterName)) { return; } - File cohctlHome = new File(home + File.separator + ".cohctl"); - File configFile = new File(cohctlHome, "cohctl.yaml"); + // Either COHCTL_HOME was not set or we failed to create a config there, try ${user.home} + String userHome = System.getProperty("user.home"); + File fileUserHome = new File(userHome); + File fileCohCtlHome = null; + + if (fileUserHome.exists() && fileUserHome.isDirectory()) { + // use ${user.home}/.cohctl + fileCohCtlHome = new File(fileUserHome, ".cohctl"); + } - if (!configFile.exists()) { - LOGGER.info("CoherenceOperator: creating default cohctl config at " + configFile.getAbsolutePath()); - if (!cohctlHome.exists()) { - cohctlHome.mkdirs(); + boolean success = false; + if (fileCohCtlHome != null) { + if (fileCohCtlHome.exists() && fileCohCtlHome.isDirectory()) { + success = tryCreateConfig(fileCohCtlHome, connectionType, protocol, port, clusterName); } - 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"); + else { + if (!fileCohCtlHome.exists()) { + LOGGER.error("CoherenceOperator: Cannot create cohctl config, directory " + fileCohCtlHome + " does not exist"); + } + else { + LOGGER.error("CoherenceOperator: Cannot create cohctl config, location " + fileCohCtlHome + " is not a directory"); + } } } + + if (!success) { + if (fileCohCtlHome != null) { + LOGGER.info("CoherenceOperator: unable to create cohctl config in \"" + fileCohCtlHome + + "\" creating cohctl config at /coherence-operator/utils"); + } + tryCreateConfig(new File("/coherence-operator/utils"), connectionType, protocol, port, clusterName); + } + } + catch (Exception e) { + LOGGER.error("Coherence Operator: Failed to create default cohctl config. " + e.getMessage()); + } + } + + protected boolean tryCreateConfig(File home, String connectionType, String protocol, String port, String clusterName) { + File configFile = new File(home, "cohctl.yaml"); + + if (configFile.exists()) { + return true; + } + + try { + LOGGER.info("CoherenceOperator: creating default cohctl config at " + configFile.getAbsolutePath()); + if (!home.exists()) { + home.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"); + } + return true; } catch (Exception e) { LOGGER.error("Coherence Operator: Failed to create default cohctl config. " + e.getMessage()); + return false; } } } diff --git a/java/operator-compatibility/image-build.sh b/java/operator-compatibility/image-build.sh index 87b1616b0..ba641d5e2 100644 --- a/java/operator-compatibility/image-build.sh +++ b/java/operator-compatibility/image-build.sh @@ -1,3 +1,3 @@ #!/bin/sh -e -docker build -t jk/coherence:1.0.0 -f operator-compatibility/target/classes/Dockerfile ./operator-compatibility \ No newline at end of file +docker build --load -t jk/coherence:1.0.0 -f operator-compatibility/target/classes/Dockerfile ./operator-compatibility \ No newline at end of file diff --git a/java/operator-compatibility/pom.xml b/java/operator-compatibility/pom.xml index dceb2a092..e79184668 100644 --- a/java/operator-compatibility/pom.xml +++ b/java/operator-compatibility/pom.xml @@ -60,6 +60,7 @@ docker build + --load -t ${coherence.compatibility.image.name} -f diff --git a/java/operator-test-helidon-2/pom.xml b/java/operator-test-helidon-2/pom.xml index 34cd98a61..a6d0a188e 100644 --- a/java/operator-test-helidon-2/pom.xml +++ b/java/operator-test-helidon-2/pom.xml @@ -55,6 +55,10 @@ coherence ${coherence.version} + + ${coherence.groupId} + coherence-json + ${coherence.groupId} coherence-cdi-server diff --git a/java/operator-test-helidon-3/pom.xml b/java/operator-test-helidon-3/pom.xml index 5a95864fc..ea15ae4ea 100644 --- a/java/operator-test-helidon-3/pom.xml +++ b/java/operator-test-helidon-3/pom.xml @@ -54,6 +54,10 @@ ${coherence.groupId} coherence + + ${coherence.groupId} + coherence-json + ${coherence.groupId} coherence-cdi-server diff --git a/java/operator-test-helidon/pom.xml b/java/operator-test-helidon/pom.xml index eece76f42..b48e9e435 100644 --- a/java/operator-test-helidon/pom.xml +++ b/java/operator-test-helidon/pom.xml @@ -54,6 +54,10 @@ ${coherence.groupId} coherence + + ${coherence.groupId} + coherence-json + ${coherence.groupId} coherence-cdi-server diff --git a/java/operator-test-spring-2/pom.xml b/java/operator-test-spring-2/pom.xml index 962eb96a5..1cf551e4c 100644 --- a/java/operator-test-spring-2/pom.xml +++ b/java/operator-test-spring-2/pom.xml @@ -47,6 +47,10 @@ ${coherence.groupId} coherence + + ${coherence.groupId} + coherence-json + org.springframework.boot spring-boot-starter-web diff --git a/java/operator-test-spring/pom.xml b/java/operator-test-spring/pom.xml index cae5357ec..01b25a566 100644 --- a/java/operator-test-spring/pom.xml +++ b/java/operator-test-spring/pom.xml @@ -46,6 +46,10 @@ ${coherence.groupId} coherence + + ${coherence.groupId} + coherence-json + org.springframework.boot spring-boot-starter-web diff --git a/java/operator-test/pom.xml b/java/operator-test/pom.xml index 5314652c2..f35187cab 100644 --- a/java/operator-test/pom.xml +++ b/java/operator-test/pom.xml @@ -41,6 +41,10 @@ ${coherence.groupId} coherence + + ${coherence.groupId} + coherence-json + ${coherence.groupId} coherence-grpc-proxy diff --git a/runner/main.go b/runner/main.go index 9581045f4..23e567132 100644 --- a/runner/main.go +++ b/runner/main.go @@ -24,6 +24,8 @@ var ( Version string // Commit is the runner Git commit injected by the Go linker at build time. Commit string + // Branch is the runner Git branch injected by the Go linker at build time. + Branch string // Date is the runner build date injected by the Go linker at build time. Date string // Author is the username of the account at build time @@ -46,7 +48,7 @@ func printVersion() { log.Info(fmt.Sprintf("Operator Version: %s", Version)) log.Info(fmt.Sprintf("Operator Build Date: %s", Date)) log.Info(fmt.Sprintf("Operator Built By: %s", Author)) - log.Info(fmt.Sprintf("Operator Git Commit: %s", Commit)) + log.Info(fmt.Sprintf("Operator Git Commit: %s (%s)", Commit, Branch)) log.Info(fmt.Sprintf("Go Version: %s", runtime.Version())) log.Info(fmt.Sprintf("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH)) } From 2a0d11bd21f36b9c65ddfc7aa24b031522f4c6a8 Mon Sep 17 00:00:00 2001 From: Jonathan Knight Date: Mon, 24 Feb 2025 08:04:49 +0300 Subject: [PATCH 06/11] Zip docs as a release artifact (#698) --- .github/workflows/release.yml | 6 +++--- Makefile | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 418ea106a..40426bc4f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -170,6 +170,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ github.event.release.upload_url }} - asset_path: /tmp/coherence-operator/_output/docs.tar.gz - asset_name: docs.tar.gz - asset_content_type: application/tar+gzip + asset_path: /tmp/coherence-operator/_output/docs.zip + asset_name: docs.zip + asset_content_type: application/zip diff --git a/Makefile b/Makefile index c9ea2ba20..fe8849fa6 100644 --- a/Makefile +++ b/Makefile @@ -2592,7 +2592,7 @@ docs: api-doc-gen mkdir -p $(BUILD_OUTPUT)/docs/images/images cp -R docs/images/* build/_output/docs/images/ find examples/ -name \*.png -exec cp {} build/_output/docs/images/images/ \; - tar -C $(BUILD_OUTPUT) -czvf $(BUILD_OUTPUT)/docs.tar.gz ./docs + cd $(BUILD_OUTPUT)/docs && zip -r $(BUILD_OUTPUT)/docs.zip * # ---------------------------------------------------------------------------------------------------------------------- # Test the documentation. From cda263a9c6f7ba575fc97bda06998a625b52425d Mon Sep 17 00:00:00 2001 From: Jonathan Knight Date: Mon, 24 Feb 2025 09:22:15 +0300 Subject: [PATCH 07/11] Changes to Spring test Docker files (#699) --- java/operator-test-spring-2/src/main/docker/Dir.Dockerfile | 2 +- java/operator-test-spring-2/src/main/docker/FatJar.Dockerfile | 2 +- java/operator-test-spring/src/main/docker/Dir.Dockerfile | 2 +- java/operator-test-spring/src/main/docker/FatJar.Dockerfile | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java/operator-test-spring-2/src/main/docker/Dir.Dockerfile b/java/operator-test-spring-2/src/main/docker/Dir.Dockerfile index 63865baed..d1d842045 100644 --- a/java/operator-test-spring-2/src/main/docker/Dir.Dockerfile +++ b/java/operator-test-spring-2/src/main/docker/Dir.Dockerfile @@ -1,6 +1,6 @@ FROM gcr.io/distroless/java17-debian12 -ADD spring /spring +COPY spring /spring WORKDIR /spring diff --git a/java/operator-test-spring-2/src/main/docker/FatJar.Dockerfile b/java/operator-test-spring-2/src/main/docker/FatJar.Dockerfile index 57cebbca7..9b18475e1 100644 --- a/java/operator-test-spring-2/src/main/docker/FatJar.Dockerfile +++ b/java/operator-test-spring-2/src/main/docker/FatJar.Dockerfile @@ -1,5 +1,5 @@ FROM gcr.io/distroless/java17-debian12 -ADD ${project.artifactId}-${project.version}.jar /app/libs/${project.artifactId}-${project.version}.jar +COPY ${project.artifactId}-${project.version}.jar /app/libs/${project.artifactId}-${project.version}.jar ENTRYPOINT ["java", "-jar", "/app/libs/${project.artifactId}-${project.version}.jar"] \ No newline at end of file diff --git a/java/operator-test-spring/src/main/docker/Dir.Dockerfile b/java/operator-test-spring/src/main/docker/Dir.Dockerfile index 676cde819..195b7afcb 100644 --- a/java/operator-test-spring/src/main/docker/Dir.Dockerfile +++ b/java/operator-test-spring/src/main/docker/Dir.Dockerfile @@ -1,6 +1,6 @@ FROM gcr.io/distroless/java17-debian12 -ADD spring /spring +COPY spring /spring WORKDIR /spring diff --git a/java/operator-test-spring/src/main/docker/FatJar.Dockerfile b/java/operator-test-spring/src/main/docker/FatJar.Dockerfile index 57cebbca7..9b18475e1 100644 --- a/java/operator-test-spring/src/main/docker/FatJar.Dockerfile +++ b/java/operator-test-spring/src/main/docker/FatJar.Dockerfile @@ -1,5 +1,5 @@ FROM gcr.io/distroless/java17-debian12 -ADD ${project.artifactId}-${project.version}.jar /app/libs/${project.artifactId}-${project.version}.jar +COPY ${project.artifactId}-${project.version}.jar /app/libs/${project.artifactId}-${project.version}.jar ENTRYPOINT ["java", "-jar", "/app/libs/${project.artifactId}-${project.version}.jar"] \ No newline at end of file From cbc74731d7b32574ab5464dd52c2859e234f0389 Mon Sep 17 00:00:00 2001 From: Jonathan Knight Date: Wed, 26 Feb 2025 09:14:38 +0300 Subject: [PATCH 08/11] Fix code review failures --- .../CoherenceOperatorLifecycleListener.java | 22 +++++++++++++++---- runner/main.go | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceOperatorLifecycleListener.java b/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceOperatorLifecycleListener.java index 39ce1930b..0f6373b27 100644 --- a/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceOperatorLifecycleListener.java +++ b/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceOperatorLifecycleListener.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. * Licensed under the Universal Permissive License v 1.0 as shown at * http://oss.oracle.com/licenses/upl. */ @@ -292,7 +292,8 @@ void initCohCtl() { } // If we have a COHCTL_HOME env var or property try to create the config there - if (cohCtlHome != null && !cohCtlHome.isEmpty() && tryCreateConfig(new File(cohCtlHome), connectionType, protocol, port, clusterName)) { + if (cohCtlHome != null && !cohCtlHome.isEmpty() + && tryCreateConfig(new File(cohCtlHome), connectionType, protocol, port, clusterName)) { return; } @@ -313,10 +314,12 @@ void initCohCtl() { } else { if (!fileCohCtlHome.exists()) { - LOGGER.error("CoherenceOperator: Cannot create cohctl config, directory " + fileCohCtlHome + " does not exist"); + LOGGER.error("CoherenceOperator: Cannot create cohctl config, directory " + + fileCohCtlHome + " does not exist"); } else { - LOGGER.error("CoherenceOperator: Cannot create cohctl config, location " + fileCohCtlHome + " is not a directory"); + LOGGER.error("CoherenceOperator: Cannot create cohctl config, location " + + fileCohCtlHome + " is not a directory"); } } } @@ -334,6 +337,17 @@ void initCohCtl() { } } + /** + * Try to create the Coherence CLI configuration. + * + * @param home the location of the CLI home directory + * @param connectionType the type of the connection http or https + * @param protocol the protocol for the connection http or https + * @param port the management over REST port + * @param clusterName the cluster name + * + * @return {@code true} of the configuration was created + */ protected boolean tryCreateConfig(File home, String connectionType, String protocol, String port, String clusterName) { File configFile = new File(home, "cohctl.yaml"); diff --git a/runner/main.go b/runner/main.go index 23e567132..46dee2fde 100644 --- a/runner/main.go +++ b/runner/main.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. * Licensed under the Universal Permissive License v 1.0 as shown at * http://oss.oracle.com/licenses/upl. */ From 8fce2fb5eb3a9a2d5e2eb63c24fa82aee22c9143 Mon Sep 17 00:00:00 2001 From: Jonathan Knight Date: Wed, 26 Feb 2025 10:35:57 +0300 Subject: [PATCH 09/11] Add logs to CLI test --- test/e2e/local/cli_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/e2e/local/cli_test.go b/test/e2e/local/cli_test.go index baa6da9f3..55104a753 100644 --- a/test/e2e/local/cli_test.go +++ b/test/e2e/local/cli_test.go @@ -29,7 +29,9 @@ func TestCoherenceCLI(t *testing.T) { hasFinalizer := controllerutil.ContainsFinalizer(&data, coh.CoherenceFinalizer) g.Expect(hasFinalizer).To(BeTrue()) - _, err := exec.Command("kubectl", "-n", data.Namespace, "exec", "storage-0", + out, err := exec.Command("kubectl", "-n", data.Namespace, "exec", "storage-0", "-c", "coherence", "--", "/coherence-operator/utils/cohctl", "get", "members").CombinedOutput() + t.Log("CLI Output:") + t.Log(string(out)) g.Expect(err).NotTo(HaveOccurred()) } From c80736ac9c03a964fe37145285f84ecb8775efa0 Mon Sep 17 00:00:00 2001 From: Jonathan Knight Date: Wed, 26 Feb 2025 10:41:25 +0300 Subject: [PATCH 10/11] Fix copyright --- test/e2e/local/cli_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/local/cli_test.go b/test/e2e/local/cli_test.go index 55104a753..fc9be2d52 100644 --- a/test/e2e/local/cli_test.go +++ b/test/e2e/local/cli_test.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. * Licensed under the Universal Permissive License v 1.0 as shown at * http://oss.oracle.com/licenses/upl. */ From 05419ab1ccd30a5307f2927e3d550ccbf42c5d07 Mon Sep 17 00:00:00 2001 From: Jonathan Knight Date: Wed, 26 Feb 2025 11:59:23 +0300 Subject: [PATCH 11/11] Add more CLI tests --- .../CoherenceOperatorLifecycleListener.java | 11 ++++++++ test/e2e/local/cli_test.go | 27 +++++++++++++++++++ test/e2e/local/deployment-cli-home.yaml | 21 +++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 test/e2e/local/deployment-cli-home.yaml diff --git a/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceOperatorLifecycleListener.java b/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceOperatorLifecycleListener.java index 0f6373b27..7049d7090 100644 --- a/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceOperatorLifecycleListener.java +++ b/java/coherence-operator/src/main/java/com/oracle/coherence/k8s/CoherenceOperatorLifecycleListener.java @@ -305,6 +305,17 @@ && tryCreateConfig(new File(cohCtlHome), connectionType, protocol, port, cluster if (fileUserHome.exists() && fileUserHome.isDirectory()) { // use ${user.home}/.cohctl fileCohCtlHome = new File(fileUserHome, ".cohctl"); + if (!fileCohCtlHome.exists()) { + try { + if (!fileCohCtlHome.mkdirs()) { + fileCohCtlHome = null; + } + } + catch (Exception e) { + LOGGER.error("CoherenceOperator: Failed to create cohctl home directory at " + fileCohCtlHome, e); + fileCohCtlHome = null; + } + } } boolean success = false; diff --git a/test/e2e/local/cli_test.go b/test/e2e/local/cli_test.go index fc9be2d52..3467343db 100644 --- a/test/e2e/local/cli_test.go +++ b/test/e2e/local/cli_test.go @@ -35,3 +35,30 @@ func TestCoherenceCLI(t *testing.T) { t.Log(string(out)) g.Expect(err).NotTo(HaveOccurred()) } + +// Test that the Coherence CLI can be executed in a Pod +func TestCoherenceCLIWithCustomHome(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-home.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()) + + out, err := exec.Command("kubectl", "-n", data.Namespace, "exec", "storage-0", + "-c", "coherence", "--", "/coherence-operator/utils/cohctl", "get", "members").CombinedOutput() + t.Log("CLI Output:") + t.Log(string(out)) + g.Expect(err).NotTo(HaveOccurred()) + + out, err = exec.Command("kubectl", "-n", data.Namespace, "exec", "storage-0", + "-c", "coherence", "--", "/coherence-operator/utils/cohctl", "--config-dir", "/test/cli", "get", "members").CombinedOutput() + t.Log("CLI Output:") + t.Log(string(out)) + g.Expect(err).NotTo(HaveOccurred()) +} diff --git a/test/e2e/local/deployment-cli-home.yaml b/test/e2e/local/deployment-cli-home.yaml new file mode 100644 index 000000000..a125fec84 --- /dev/null +++ b/test/e2e/local/deployment-cli-home.yaml @@ -0,0 +1,21 @@ +apiVersion: coherence.oracle.com/v1 +kind: Coherence +metadata: + name: storage +spec: + env: + - name: COH_SKIP_SITE + value: "true" + - name: COHCTL_HOME + value: /test/cli + volumeMounts: + - mountPath: /test/cli + name: cli + readOnly: false + volumes: + - name: cli + emptyDir: {} + + + +