feat: Disable plugin registry if openVSX registry is configured (#1843)

* feat: Disable plugin registry if openVSX registry is configured

Signed-off-by: Anatolii Bazko <abazko@redhat.com>
pull/1827/merge
Anatolii Bazko 2024-06-04 10:42:53 +02:00 committed by GitHub
parent 84673c8514
commit 618ad1f1a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 349 additions and 257 deletions

View File

@ -78,7 +78,7 @@ jobs:
registry: quay.io registry: quay.io
- name: Build catalog source - name: Build catalog source
run: | run: |
./build/scripts/release/editors-definitions.sh add-env-vars ./build/scripts/release/editors-definitions.sh update-manager-yaml
make update-dev-resources make update-dev-resources
./build/scripts/release/addDigests.sh -s $(make csv-path CHANNEL=next) -t next ./build/scripts/release/addDigests.sh -s $(make csv-path CHANNEL=next) -t next
./build/scripts/olm/release-catalog.sh \ ./build/scripts/olm/release-catalog.sh \

View File

@ -202,6 +202,102 @@ metadata:
kubernetes.io/metadata.name: ${USER_NAMESPACE} kubernetes.io/metadata.name: ${USER_NAMESPACE}
EOF EOF
kubectl apply -f - <<EOF
apiVersion: workspace.devfile.io/v1alpha2
kind: DevWorkspaceTemplate
metadata:
name: che-code
namespace: ${USER_NAMESPACE}
spec:
commands:
- apply:
component: che-code-injector
id: init-container-command
- exec:
commandLine: nohup /checode/entrypoint-volume.sh > /checode/entrypoint-logs.txt
2>&1 &
component: che-code-runtime-description
id: init-che-code-command
components:
- container:
command:
- /entrypoint-init-container.sh
cpuLimit: 500m
cpuRequest: 30m
env:
- name: CHE_DASHBOARD_URL
value: https://$(minikube ip).nip.io
- name: OPENVSX_REGISTRY_URL
value: https://open-vsx.org
image: quay.io/che-incubator/che-code:latest
memoryLimit: 256Mi
memoryRequest: 32Mi
sourceMapping: /projects
volumeMounts:
- name: checode
path: /checode
name: che-code-injector
- attributes:
app.kubernetes.io/component: che-code-runtime
app.kubernetes.io/part-of: che-code.eclipse.org
controller.devfile.io/container-contribution: true
container:
cpuLimit: 500m
cpuRequest: 30m
endpoints:
- attributes:
cookiesAuthEnabled: true
discoverable: false
type: main
urlRewriteSupported: true
exposure: public
name: che-code
protocol: https
secure: true
targetPort: 3100
- attributes:
discoverable: false
urlRewriteSupported: false
exposure: public
name: code-redirect-1
protocol: https
targetPort: 13131
- attributes:
discoverable: false
urlRewriteSupported: false
exposure: public
name: code-redirect-2
protocol: https
targetPort: 13132
- attributes:
discoverable: false
urlRewriteSupported: false
exposure: public
name: code-redirect-3
protocol: https
targetPort: 13133
env:
- name: CHE_DASHBOARD_URL
value: https://$(minikube ip).nip.io
- name: OPENVSX_REGISTRY_URL
value: https://open-vsx.org
image: quay.io/devfile/universal-developer-image:ubi8-latest
memoryLimit: 1024Mi
memoryRequest: 256Mi
sourceMapping: /projects
volumeMounts:
- name: checode
path: /checode
name: che-code-runtime-description
- name: checode
volume: {}
events:
postStart:
- init-che-code-command
preStart:
- init-container-command
EOF
kubectl apply -f - <<EOF kubectl apply -f - <<EOF
kind: DevWorkspace kind: DevWorkspace
apiVersion: workspace.devfile.io/v1alpha2 apiVersion: workspace.devfile.io/v1alpha2
@ -209,11 +305,12 @@ metadata:
name: ${DEV_WORKSPACE_NAME} name: ${DEV_WORKSPACE_NAME}
namespace: ${USER_NAMESPACE} namespace: ${USER_NAMESPACE}
spec: spec:
contributions:
- kubernetes:
name: che-code
name: editor
routingClass: che routingClass: che
started: false started: false
contributions:
- name: ide
uri: http://plugin-registry.eclipse-che.svc:8080/v3/plugins/che-incubator/che-code/insiders/devfile.yaml
template: template:
attributes: attributes:
controller.devfile.io/storage-type: ephemeral controller.devfile.io/storage-type: ephemeral
@ -229,6 +326,7 @@ EOF
startAndWaitDevWorkspace() { startAndWaitDevWorkspace() {
# pre-pull image for faster workspace startup # pre-pull image for faster workspace startup
minikube image pull quay.io/devfile/universal-developer-image:ubi8-latest minikube image pull quay.io/devfile/universal-developer-image:ubi8-latest
minikube image pull quay.io/che-incubator/che-code:latest
kubectl patch devworkspace ${DEV_WORKSPACE_NAME} -p '{"spec":{"started":true}}' --type=merge -n ${USER_NAMESPACE} kubectl patch devworkspace ${DEV_WORKSPACE_NAME} -p '{"spec":{"started":true}}' --type=merge -n ${USER_NAMESPACE}
kubectl wait devworkspace ${DEV_WORKSPACE_NAME} -n ${USER_NAMESPACE} --for=jsonpath='{.status.phase}'=Running --timeout=300s kubectl wait devworkspace ${DEV_WORKSPACE_NAME} -n ${USER_NAMESPACE} --for=jsonpath='{.status.phase}'=Running --timeout=300s

View File

@ -53,7 +53,6 @@ runTest() {
popd popd
# Free up some resources # Free up some resources
minikube image rm quay.io/eclipse/che-plugin-registry:${LAST_PACKAGE_VERSION}
minikube image rm quay.io/eclipse/che-dashboard:${LAST_PACKAGE_VERSION} minikube image rm quay.io/eclipse/che-dashboard:${LAST_PACKAGE_VERSION}
minikube image rm quay.io/eclipse/che-server:${LAST_PACKAGE_VERSION} minikube image rm quay.io/eclipse/che-server:${LAST_PACKAGE_VERSION}
minikube image rm quay.io/eclipse/che-operator:${LAST_PACKAGE_VERSION} minikube image rm quay.io/eclipse/che-operator:${LAST_PACKAGE_VERSION}

View File

@ -48,7 +48,6 @@ runTest() {
popd popd
# Free up some resources # Free up some resources
minikube image rm quay.io/eclipse/che-plugin-registry:${PREVIOUS_PACKAGE_VERSION}
minikube image rm quay.io/eclipse/che-dashboard:${PREVIOUS_PACKAGE_VERSION} minikube image rm quay.io/eclipse/che-dashboard:${PREVIOUS_PACKAGE_VERSION}
minikube image rm quay.io/eclipse/che-server:${PREVIOUS_PACKAGE_VERSION} minikube image rm quay.io/eclipse/che-server:${PREVIOUS_PACKAGE_VERSION}
minikube image rm quay.io/eclipse/che-operator:${PREVIOUS_PACKAGE_VERSION} minikube image rm quay.io/eclipse/che-operator:${PREVIOUS_PACKAGE_VERSION}

View File

@ -37,17 +37,15 @@ usage () {
echo echo
echo "Usage:" echo "Usage:"
echo -e "\t$0 release --version RELEASE_VERSION" echo -e "\t$0 release --version RELEASE_VERSION"
echo -e "\t$0 add-env-vars" echo -e "\t$0 update-manager-yaml"
} }
release() { release() {
if [[ ! ${VERSION} ]]; then usage; exit 1; fi if [[ ! ${VERSION} ]]; then usage; exit 1; fi
yq -riY ".metadata.attributes.version = \"${VERSION}\"" "${EDITORS_DEFINITIONS_DIR}/che-code-latest.yaml"
yq -riY "(.components[] | select(.name==\"che-code-injector\") | .container.image) = \"quay.io/che-incubator/che-code:${VERSION}\"" "${EDITORS_DEFINITIONS_DIR}/che-code-latest.yaml" yq -riY "(.components[] | select(.name==\"che-code-injector\") | .container.image) = \"quay.io/che-incubator/che-code:${VERSION}\"" "${EDITORS_DEFINITIONS_DIR}/che-code-latest.yaml"
} }
addEnvVars() { updateManagerYaml() {
for EDITOR_DEFINITION_FILE in $(find "${EDITORS_DEFINITIONS_DIR}" -name "*.yaml"); do for EDITOR_DEFINITION_FILE in $(find "${EDITORS_DEFINITIONS_DIR}" -name "*.yaml"); do
NAME=$(yq -r '.metadata.name' "${EDITOR_DEFINITION_FILE}") NAME=$(yq -r '.metadata.name' "${EDITOR_DEFINITION_FILE}")
VERSION=$(yq -r '.metadata.attributes.version' "${EDITOR_DEFINITION_FILE}") VERSION=$(yq -r '.metadata.attributes.version' "${EDITOR_DEFINITION_FILE}")
@ -74,7 +72,7 @@ init "$@"
pushd "${OPERATOR_REPO}" >/dev/null pushd "${OPERATOR_REPO}" >/dev/null
case $COMMAND in case $COMMAND in
'release') release;; 'release') release;;
'add-env-vars') addEnvVars;; 'update-manager-yaml'|'add-env-vars') updateManagerYaml;;
*) usage; exit 1;; *) usage; exit 1;;
esac esac
popd >/dev/null popd >/dev/null

View File

@ -183,10 +183,12 @@ releaseEditorsDefinitions() {
echo "[INFO] Releasing editor definitions" echo "[INFO] Releasing editor definitions"
. "${OPERATOR_REPO}/build/scripts/release/editors-definitions.sh" release --version "${RELEASE}" . "${OPERATOR_REPO}/build/scripts/release/editors-definitions.sh" release --version "${RELEASE}"
. "${OPERATOR_REPO}/build/scripts/release/editors-definitions.sh" add-env-vars . "${OPERATOR_REPO}/build/scripts/release/editors-definitions.sh" update-manager-yaml
make bundle CHANNEL=stable
git add editors-definitions git add editors-definitions
git add "${OPERATOR_REPO}/config/manager/manager.yaml" git add "${OPERATOR_REPO}/config/manager/manager.yaml"
git add "${OPERATOR_REPO}/bundle/stable"
git commit -m "ci: Release editors definitions to $RELEASE" --signoff git commit -m "ci: Release editors definitions to $RELEASE" --signoff
} }

View File

@ -46,6 +46,7 @@ metadata:
} }
], ],
"externalDevfileRegistry": true, "externalDevfileRegistry": true,
"externalPluginRegistry": true,
"workspaceNamespaceDefault": "<username>-che" "workspaceNamespaceDefault": "<username>-che"
}, },
"storage": { "storage": {
@ -69,6 +70,9 @@ metadata:
"url": "https://registry.devfile.io" "url": "https://registry.devfile.io"
} }
] ]
},
"pluginRegistry": {
"disableInternalRegistry": true
} }
}, },
"containerRegistry": {}, "containerRegistry": {},
@ -100,7 +104,7 @@ metadata:
operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 operators.operatorframework.io/project_layout: go.kubebuilder.io/v3
repository: https://github.com/eclipse-che/che-operator repository: https://github.com/eclipse-che/che-operator
support: Eclipse Foundation support: Eclipse Foundation
name: eclipse-che.v7.87.0-870.next name: eclipse-che.v7.87.0-871.next
namespace: placeholder namespace: placeholder
spec: spec:
apiservicedefinitions: {} apiservicedefinitions: {}
@ -1032,7 +1036,7 @@ spec:
minKubeVersion: 1.19.0 minKubeVersion: 1.19.0
provider: provider:
name: Eclipse Foundation name: Eclipse Foundation
version: 7.87.0-870.next version: 7.87.0-871.next
webhookdefinitions: webhookdefinitions:
- admissionReviewVersions: - admissionReviewVersions:
- v1 - v1

View File

@ -18,6 +18,7 @@ metadata:
spec: spec:
server: server:
workspaceNamespaceDefault: '<username>-che' workspaceNamespaceDefault: '<username>-che'
externalPluginRegistry: true
externalDevfileRegistry: true externalDevfileRegistry: true
externalDevfileRegistries: externalDevfileRegistries:
- url: 'https://registry.devfile.io' - url: 'https://registry.devfile.io'

View File

@ -17,6 +17,8 @@ metadata:
namespace: eclipse-che namespace: eclipse-che
spec: spec:
components: components:
pluginRegistry:
disableInternalRegistry: true
devfileRegistry: devfileRegistry:
disableInternalRegistry: true disableInternalRegistry: true
externalDevfileRegistries: externalDevfileRegistries:

View File

@ -15,6 +15,8 @@ package che
import ( import (
"context" "context"
editorsdefinitions "github.com/eclipse-che/che-operator/pkg/deploy/editors-definitions"
"github.com/eclipse-che/che-operator/pkg/common/test" "github.com/eclipse-che/che-operator/pkg/common/test"
containerbuild "github.com/eclipse-che/che-operator/pkg/deploy/container-build" containerbuild "github.com/eclipse-che/che-operator/pkg/deploy/container-build"
@ -110,6 +112,7 @@ func NewReconciler(
} }
reconcileManager.RegisterReconciler(devfileregistry.NewDevfileRegistryReconciler()) reconcileManager.RegisterReconciler(devfileregistry.NewDevfileRegistryReconciler())
reconcileManager.RegisterReconciler(pluginregistry.NewPluginRegistryReconciler()) reconcileManager.RegisterReconciler(pluginregistry.NewPluginRegistryReconciler())
reconcileManager.RegisterReconciler(editorsdefinitions.NewEditorsDefinitionsReconciler())
reconcileManager.RegisterReconciler(dashboard.NewDashboardReconciler()) reconcileManager.RegisterReconciler(dashboard.NewDashboardReconciler())
reconcileManager.RegisterReconciler(gateway.NewGatewayReconciler()) reconcileManager.RegisterReconciler(gateway.NewGatewayReconciler())
reconcileManager.RegisterReconciler(server.NewCheServerReconciler()) reconcileManager.RegisterReconciler(server.NewCheServerReconciler())

View File

@ -17,6 +17,8 @@ metadata:
namespace: eclipse-che namespace: eclipse-che
spec: spec:
components: components:
pluginRegistry:
disableInternalRegistry: true
devfileRegistry: devfileRegistry:
disableInternalRegistry: true disableInternalRegistry: true
externalDevfileRegistries: externalDevfileRegistries:

View File

@ -17,6 +17,8 @@ metadata:
namespace: eclipse-che namespace: eclipse-che
spec: spec:
components: components:
pluginRegistry:
disableInternalRegistry: true
devfileRegistry: devfileRegistry:
disableInternalRegistry: true disableInternalRegistry: true
externalDevfileRegistries: externalDevfileRegistries:

View File

@ -17,6 +17,8 @@ metadata:
namespace: eclipse-che namespace: eclipse-che
spec: spec:
components: components:
pluginRegistry:
disableInternalRegistry: true
devfileRegistry: devfileRegistry:
disableInternalRegistry: true disableInternalRegistry: true
externalDevfileRegistries: externalDevfileRegistries:

View File

@ -122,8 +122,8 @@ func (cb *ContainerBuildReconciler) syncSCC(ctx *chetypes.DeployContext) (bool,
}) })
} }
} else { } else {
// Create a new SCC. If custom SCC exists then it won't be touched. // Create a new SCC.
return deploy.Create(ctx, cb.getSccSpec(ctx)) return deploy.CreateIgnoreIfExists(ctx, cb.getSccSpec(ctx))
} }
return true, nil return true, nil

View File

@ -10,7 +10,7 @@
// Red Hat, Inc. - initial API and implementation // Red Hat, Inc. - initial API and implementation
// //
package pluginregistry package editorsdefinitions
import ( import (
"fmt" "fmt"
@ -18,21 +18,47 @@ import (
"path/filepath" "path/filepath"
"regexp" "regexp"
"github.com/eclipse-che/che-operator/pkg/common/chetypes"
"github.com/eclipse-che/che-operator/pkg/common/constants"
"github.com/eclipse-che/che-operator/pkg/common/utils" "github.com/eclipse-che/che-operator/pkg/common/utils"
"github.com/eclipse-che/che-operator/pkg/deploy"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
"github.com/eclipse-che/che-operator/pkg/common/chetypes"
"github.com/eclipse-che/che-operator/pkg/common/constants"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"github.com/eclipse-che/che-operator/pkg/deploy"
) )
var ( var (
editorsDefinitionsDir = "/tmp/editors-definitions" editorsDefinitionsDir = "/tmp/editors-definitions"
editorsDefinitionsConfigMapName = "editors-definitions" editorsDefinitionsConfigMapName = "editors-definitions"
logger = ctrl.Log.WithName("editorsdefinitions")
) )
func (p *PluginRegistryReconciler) syncEditors(ctx *chetypes.DeployContext) (bool, error) { type EditorsDefinitionsReconciler struct {
deploy.Reconcilable
}
func NewEditorsDefinitionsReconciler() *EditorsDefinitionsReconciler {
return &EditorsDefinitionsReconciler{}
}
func (p *EditorsDefinitionsReconciler) Reconcile(ctx *chetypes.DeployContext) (reconcile.Result, bool, error) {
done, err := p.syncEditors(ctx)
if !done {
return reconcile.Result{}, false, err
}
return reconcile.Result{}, true, nil
}
func (p *EditorsDefinitionsReconciler) Finalize(ctx *chetypes.DeployContext) bool {
return true
}
func (p *EditorsDefinitionsReconciler) syncEditors(ctx *chetypes.DeployContext) (bool, error) {
editorDefinitions, err := readEditorDefinitions() editorDefinitions, err := readEditorDefinitions()
if err != nil { if err != nil {
return false, err return false, err
@ -66,11 +92,11 @@ func readEditorDefinitions() (map[string][]byte, error) {
var devfile map[string]interface{} var devfile map[string]interface{}
err = yaml.Unmarshal(editorContent, &devfile) err = yaml.Unmarshal(editorContent, &devfile)
if err != nil { if err != nil {
return editorDefinitions, err logger.Error(err, "Failed to unmarshal editor definition", "file", fileName)
continue
} }
updateEditorDefinitionImageFromEnv(devfile) updateEditorDefinitionImages(devfile)
editorContent, err = yaml.Marshal(devfile) editorContent, err = yaml.Marshal(devfile)
if err != nil { if err != nil {
return editorDefinitions, err return editorDefinitions, err
@ -83,7 +109,7 @@ func readEditorDefinitions() (map[string][]byte, error) {
return editorDefinitions, nil return editorDefinitions, nil
} }
func updateEditorDefinitionImageFromEnv(devfile map[string]interface{}) { func updateEditorDefinitionImages(devfile map[string]interface{}) {
notAllowedCharsReg, _ := regexp.Compile("[^a-zA-Z0-9]+") notAllowedCharsReg, _ := regexp.Compile("[^a-zA-Z0-9]+")
metadata := devfile["metadata"].(map[string]interface{}) metadata := devfile["metadata"].(map[string]interface{})

View File

@ -10,7 +10,7 @@
// Red Hat, Inc. - initial API and implementation // Red Hat, Inc. - initial API and implementation
// //
package pluginregistry package editorsdefinitions
import ( import (
"os" "os"
@ -61,6 +61,7 @@ func TestSyncEditorDefinitions(t *testing.T) {
editorDefinitions, err := readEditorDefinitions() editorDefinitions, err := readEditorDefinitions()
assert.NoError(t, err) assert.NoError(t, err)
assert.NotEmpty(t, editorDefinitions) assert.NotEmpty(t, editorDefinitions)
assert.Len(t, editorDefinitions, 1)
done, err := syncEditorDefinitions(ctx, editorDefinitions) done, err := syncEditorDefinitions(ctx, editorDefinitions)
assert.NoError(t, err) assert.NoError(t, err)

View File

@ -0,0 +1,28 @@
//
// Copyright (c) 2019-2024 Red Hat, Inc.
// This program and the accompanying materials are made
// available under the terms of the Eclipse Public License 2.0
// which is available at https://www.eclipse.org/legal/epl-2.0/
//
// SPDX-License-Identifier: EPL-2.0
//
// Contributors:
// Red Hat, Inc. - initial API and implementation
//
package editorsdefinitions
import (
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults"
"github.com/eclipse-che/che-operator/pkg/common/test"
)
func init() {
test.EnableTestMode()
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
defaults.InitializeForTesting("../../../config/manager/manager.yaml")
editorsDefinitionsDir = "./test-editors-definitions"
}

View File

@ -15,6 +15,7 @@ metadata:
name: che-code name: che-code
attributes: attributes:
version: 1.2.3 version: 1.2.3
publisher: test
components: components:
- name: component-a - name: component-a
container: container:

View File

@ -143,8 +143,10 @@ func getImagePullerCustomResourceName(ctx *chetypes.DeployContext) string {
} }
func getDefaultImages(ctx *chetypes.DeployContext) string { func getDefaultImages(ctx *chetypes.DeployContext) string {
urls := collectRegistriesUrls(ctx) allImages := make(map[string]bool)
allImages := fetchImagesFromRegistries(urls, ctx)
addImagesFromRegistries(ctx, allImages)
addImagesFromEditorsDefinitions(allImages)
// having them sorted, prevents from constant changing CR spec // having them sorted, prevents from constant changing CR spec
sortedImages := sortImages(allImages) sortedImages := sortImages(allImages)
@ -154,18 +156,6 @@ func getDefaultImages(ctx *chetypes.DeployContext) string {
func collectRegistriesUrls(ctx *chetypes.DeployContext) []string { func collectRegistriesUrls(ctx *chetypes.DeployContext) []string {
urls := make([]string, 0) urls := make([]string, 0)
if ctx.CheCluster.Status.PluginRegistryURL != "" {
urls = append(
urls,
fmt.Sprintf(
"http://%s.%s.svc:8080/v3/%s",
constants.PluginRegistryName,
ctx.CheCluster.Namespace,
"external_images.txt",
),
)
}
if ctx.CheCluster.Status.DevfileRegistryURL != "" { if ctx.CheCluster.Status.DevfileRegistryURL != "" {
urls = append( urls = append(
urls, urls,
@ -181,9 +171,8 @@ func collectRegistriesUrls(ctx *chetypes.DeployContext) []string {
return urls return urls
} }
func fetchImagesFromRegistries(urls []string, ctx *chetypes.DeployContext) map[string]bool { func addImagesFromRegistries(ctx *chetypes.DeployContext, allImages map[string]bool) {
// return as map to make the list unique urls := collectRegistriesUrls(ctx)
allImages := make(map[string]bool)
for _, url := range urls { for _, url := range urls {
images, err := fetchImagesFromUrl(url, ctx) images, err := fetchImagesFromUrl(url, ctx)
@ -195,8 +184,13 @@ func fetchImagesFromRegistries(urls []string, ctx *chetypes.DeployContext) map[s
} }
} }
} }
}
return allImages func addImagesFromEditorsDefinitions(allImages map[string]bool) {
envs := utils.GetEnvsByRegExp("RELATED_IMAGE_editor_definition_.*")
for _, env := range envs {
allImages[env.Value] = true
}
} }
func sortImages(images map[string]bool) []string { func sortImages(images map[string]bool) []string {

View File

@ -23,6 +23,4 @@ func init() {
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4) infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
defaults.InitializeForTesting("../../../config/manager/manager.yaml") defaults.InitializeForTesting("../../../config/manager/manager.yaml")
editorsDefinitionsDir = "./test-editors-definitions"
} }

View File

@ -16,9 +16,6 @@ import (
"fmt" "fmt"
"strings" "strings"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"github.com/eclipse-che/che-operator/pkg/common/chetypes" "github.com/eclipse-che/che-operator/pkg/common/chetypes"
"github.com/eclipse-che/che-operator/pkg/common/constants" "github.com/eclipse-che/che-operator/pkg/common/constants"
"github.com/eclipse-che/che-operator/pkg/deploy/gateway" "github.com/eclipse-che/che-operator/pkg/deploy/gateway"
@ -38,25 +35,16 @@ func NewPluginRegistryReconciler() *PluginRegistryReconciler {
func (p *PluginRegistryReconciler) Reconcile(ctx *chetypes.DeployContext) (reconcile.Result, bool, error) { func (p *PluginRegistryReconciler) Reconcile(ctx *chetypes.DeployContext) (reconcile.Result, bool, error) {
if ctx.CheCluster.Spec.Components.PluginRegistry.DisableInternalRegistry { if ctx.CheCluster.Spec.Components.PluginRegistry.DisableInternalRegistry {
_, _ = deploy.DeleteNamespacedObject(ctx, constants.PluginRegistryName, &corev1.Service{})
_, _ = deploy.DeleteNamespacedObject(ctx, constants.PluginRegistryName, &corev1.ConfigMap{})
_, _ = deploy.DeleteNamespacedObject(ctx, editorsDefinitionsConfigMapName, &corev1.ConfigMap{})
_, _ = deploy.DeleteNamespacedObject(ctx, gateway.GatewayConfigMapNamePrefix+constants.PluginRegistryName, &corev1.ConfigMap{})
_, _ = deploy.DeleteNamespacedObject(ctx, constants.PluginRegistryName, &appsv1.Deployment{})
if ctx.CheCluster.Status.PluginRegistryURL != "" { if ctx.CheCluster.Status.PluginRegistryURL != "" {
ctx.CheCluster.Status.PluginRegistryURL = "" ctx.CheCluster.Status.PluginRegistryURL = ""
err := deploy.UpdateCheCRStatus(ctx, "PluginRegistryURL", "") err := deploy.UpdateCheCRStatus(ctx, "PluginRegistryURL", "")
return reconcile.Result{}, err == nil, err return reconcile.Result{}, err == nil, err
} }
return reconcile.Result{}, true, nil
} }
done, err := p.syncEditors(ctx) done, err := p.syncService(ctx)
if !done {
return reconcile.Result{}, false, err
}
done, err = p.syncService(ctx)
if !done { if !done {
return reconcile.Result{}, false, err return reconcile.Result{}, false, err
} }

View File

@ -16,7 +16,6 @@ import (
"github.com/devfile/devworkspace-operator/pkg/infrastructure" "github.com/devfile/devworkspace-operator/pkg/infrastructure"
"github.com/eclipse-che/che-operator/pkg/common/test" "github.com/eclipse-che/che-operator/pkg/common/test"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1" appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@ -37,7 +36,6 @@ func TestPluginRegistryReconcile(t *testing.T) {
assert.True(t, test.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: "plugin-registry", Namespace: "eclipse-che"}, &corev1.Service{})) assert.True(t, test.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: "plugin-registry", Namespace: "eclipse-che"}, &corev1.Service{}))
assert.True(t, test.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: "plugin-registry", Namespace: "eclipse-che"}, &corev1.ConfigMap{})) assert.True(t, test.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: "plugin-registry", Namespace: "eclipse-che"}, &corev1.ConfigMap{}))
assert.True(t, test.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: "editors-definitions", Namespace: "eclipse-che"}, &corev1.ConfigMap{}))
assert.True(t, test.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: "plugin-registry", Namespace: "eclipse-che"}, &appsv1.Deployment{})) assert.True(t, test.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: "plugin-registry", Namespace: "eclipse-che"}, &appsv1.Deployment{}))
assert.NotEmpty(t, ctx.CheCluster.Status.PluginRegistryURL) assert.NotEmpty(t, ctx.CheCluster.Status.PluginRegistryURL)
} }

View File

@ -37,13 +37,11 @@ func NewPostgresReconciler() *PostgresReconciler {
func (p *PostgresReconciler) Reconcile(ctx *chetypes.DeployContext) (reconcile.Result, bool, error) { func (p *PostgresReconciler) Reconcile(ctx *chetypes.DeployContext) (reconcile.Result, bool, error) {
// PostgreSQL component is not used anymore // PostgreSQL component is not used anymore
_, _ = p.syncDeployment(ctx) _, _ = deploy.DeleteNamespacedObject(ctx, postgresComponentName, &appsv1.Deployment{})
_, _ = p.syncPVC(ctx) _, _ = deploy.DeleteNamespacedObject(ctx, backupServerComponentName, &appsv1.Deployment{})
_, _ = p.syncCredentials(ctx) _, _ = deploy.DeleteNamespacedObject(ctx, defaultPostgresVolumeClaimName, &corev1.PersistentVolumeClaim{})
_, _ = p.syncService(ctx) _, _ = deploy.DeleteNamespacedObject(ctx, defaultPostgresCredentialsSecret, &corev1.Secret{})
_, _ = deploy.DeleteNamespacedObject(ctx, postgresComponentName, &corev1.Service{})
// Backup server component is not used anymore
_, _ = p.syncBackupDeployment(ctx)
return reconcile.Result{}, true, nil return reconcile.Result{}, true, nil
} }
@ -51,23 +49,3 @@ func (p *PostgresReconciler) Reconcile(ctx *chetypes.DeployContext) (reconcile.R
func (p *PostgresReconciler) Finalize(ctx *chetypes.DeployContext) bool { func (p *PostgresReconciler) Finalize(ctx *chetypes.DeployContext) bool {
return true return true
} }
func (p *PostgresReconciler) syncService(ctx *chetypes.DeployContext) (bool, error) {
return deploy.DeleteNamespacedObject(ctx, postgresComponentName, &corev1.Service{})
}
func (p *PostgresReconciler) syncPVC(ctx *chetypes.DeployContext) (bool, error) {
return deploy.DeleteNamespacedObject(ctx, defaultPostgresVolumeClaimName, &corev1.PersistentVolumeClaim{})
}
func (p *PostgresReconciler) syncDeployment(ctx *chetypes.DeployContext) (bool, error) {
return deploy.DeleteNamespacedObject(ctx, postgresComponentName, &appsv1.Deployment{})
}
func (p *PostgresReconciler) syncCredentials(ctx *chetypes.DeployContext) (bool, error) {
return deploy.DeleteNamespacedObject(ctx, defaultPostgresCredentialsSecret, &corev1.Secret{})
}
func (p *PostgresReconciler) syncBackupDeployment(ctx *chetypes.DeployContext) (bool, error) {
return deploy.DeleteNamespacedObject(ctx, backupServerComponentName, &appsv1.Deployment{})
}

View File

@ -20,14 +20,7 @@ import (
) )
func SyncServiceAccountToCluster(deployContext *chetypes.DeployContext, name string) (bool, error) { func SyncServiceAccountToCluster(deployContext *chetypes.DeployContext, name string) (bool, error) {
saSpec := getServiceAccountSpec(deployContext, name) sa := &corev1.ServiceAccount{
_, err := CreateIfNotExists(deployContext, saSpec)
return err == nil, err
}
func getServiceAccountSpec(deployContext *chetypes.DeployContext, name string) *corev1.ServiceAccount {
labels := GetLabels(defaults.GetCheFlavor())
serviceAccount := &corev1.ServiceAccount{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
Kind: "ServiceAccount", Kind: "ServiceAccount",
APIVersion: "v1", APIVersion: "v1",
@ -35,9 +28,9 @@ func getServiceAccountSpec(deployContext *chetypes.DeployContext, name string) *
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: deployContext.CheCluster.Namespace, Namespace: deployContext.CheCluster.Namespace,
Labels: labels, Labels: GetLabels(defaults.GetCheFlavor()),
}, },
} }
return serviceAccount return CreateIgnoreIfExists(deployContext, sa)
} }

View File

@ -0,0 +1,29 @@
//
// Copyright (c) 2019-2023 Red Hat, Inc.
// This program and the accompanying materials are made
// available under the terms of the Eclipse Public License 2.0
// which is available at https://www.eclipse.org/legal/epl-2.0/
//
// SPDX-License-Identifier: EPL-2.0
//
// Contributors:
// Red Hat, Inc. - initial API and implementation
//
package deploy
import (
"github.com/eclipse-che/che-operator/pkg/common/test"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/runtime"
"testing"
)
func TestSyncServiceAccountToCluster(t *testing.T) {
ctx := test.GetDeployContext(nil, []runtime.Object{})
done, err := SyncServiceAccountToCluster(ctx, "test")
assert.NoError(t, err)
assert.True(t, done)
}

View File

@ -54,7 +54,7 @@ func SyncWithClient(cli client.Client, deployContext *chetypes.DeployContext, bl
} }
key := types.NamespacedName{Name: blueprint.GetName(), Namespace: blueprint.GetNamespace()} key := types.NamespacedName{Name: blueprint.GetName(), Namespace: blueprint.GetNamespace()}
exists, err := GetWithClient(cli, key, actual.(client.Object)) exists, err := doGet(context.TODO(), cli, key, actual.(client.Object))
if err != nil { if err != nil {
return false, err return false, err
} }
@ -62,17 +62,18 @@ func SyncWithClient(cli client.Client, deployContext *chetypes.DeployContext, bl
// set GroupVersionKind (it might be empty) // set GroupVersionKind (it might be empty)
actual.GetObjectKind().SetGroupVersionKind(runtimeObject.GetObjectKind().GroupVersionKind()) actual.GetObjectKind().SetGroupVersionKind(runtimeObject.GetObjectKind().GroupVersionKind())
if !exists { if !exists {
return CreateWithClient(cli, deployContext, blueprint, false) return doCreate(context.TODO(), cli, deployContext, blueprint, false)
} }
return UpdateWithClient(cli, deployContext, actual.(client.Object), blueprint, diffOpts...) return doUpdate(cli, deployContext, actual.(client.Object), blueprint, diffOpts...)
} }
// Gets object by key. // Get gets object.
// Returns true if object exists otherwise returns false. // Returns true if object exists otherwise returns false.
// Returns error if object cannot be retrieved otherwise returns nil.
func Get(deployContext *chetypes.DeployContext, key client.ObjectKey, actual client.Object) (bool, error) { func Get(deployContext *chetypes.DeployContext, key client.ObjectKey, actual client.Object) (bool, error) {
cli := getClientForObject(key.Namespace, deployContext) cli := getClientForObject(key.Namespace, deployContext)
return GetWithClient(cli, key, actual) return doGet(context.TODO(), cli, key, actual)
} }
// Gets namespaced scope object by name // Gets namespaced scope object by name
@ -80,7 +81,7 @@ func Get(deployContext *chetypes.DeployContext, key client.ObjectKey, actual cli
func GetNamespacedObject(deployContext *chetypes.DeployContext, name string, actual client.Object) (bool, error) { func GetNamespacedObject(deployContext *chetypes.DeployContext, name string, actual client.Object) (bool, error) {
client := deployContext.ClusterAPI.Client client := deployContext.ClusterAPI.Client
key := types.NamespacedName{Name: name, Namespace: deployContext.CheCluster.Namespace} key := types.NamespacedName{Name: name, Namespace: deployContext.CheCluster.Namespace}
return GetWithClient(client, key, actual) return doGet(context.TODO(), client, key, actual)
} }
// Gets cluster scope object by name // Gets cluster scope object by name
@ -88,34 +89,15 @@ func GetNamespacedObject(deployContext *chetypes.DeployContext, name string, act
func GetClusterObject(deployContext *chetypes.DeployContext, name string, actual client.Object) (bool, error) { func GetClusterObject(deployContext *chetypes.DeployContext, name string, actual client.Object) (bool, error) {
client := deployContext.ClusterAPI.NonCachingClient client := deployContext.ClusterAPI.NonCachingClient
key := types.NamespacedName{Name: name} key := types.NamespacedName{Name: name}
return GetWithClient(client, key, actual) return doGet(context.TODO(), client, key, actual)
} }
// Creates object. // CreateIgnoreIfExists creates object.
// Return true if a new object is created, false if it has been already created or error occurred. // Return true if a new object is created or object already exists, otherwise returns false.
func CreateIfNotExists(deployContext *chetypes.DeployContext, blueprint client.Object) (isCreated bool, err error) { // Throws error if object cannot be created otherwise returns nil.
func CreateIgnoreIfExists(deployContext *chetypes.DeployContext, blueprint client.Object) (bool, error) {
cli := getClientForObject(blueprint.GetNamespace(), deployContext) cli := getClientForObject(blueprint.GetNamespace(), deployContext)
return CreateIfNotExistsWithClient(cli, deployContext, blueprint) return doCreate(context.TODO(), cli, deployContext, blueprint, true)
}
func CreateIfNotExistsWithClient(cli client.Client, deployContext *chetypes.DeployContext, blueprint client.Object) (isCreated bool, err error) {
key := types.NamespacedName{Name: blueprint.GetName(), Namespace: blueprint.GetNamespace()}
actual := blueprint.DeepCopyObject().(client.Object)
exists, err := GetWithClient(cli, key, actual)
if exists {
return false, nil
} else if err != nil {
return false, err
}
return CreateWithClient(cli, deployContext, blueprint, false)
}
// Creates object.
// Return true if a new object is created otherwise returns false.
func Create(deployContext *chetypes.DeployContext, blueprint client.Object) (bool, error) {
client := getClientForObject(blueprint.GetNamespace(), deployContext)
return CreateWithClient(client, deployContext, blueprint, false)
} }
// Deletes object. // Deletes object.
@ -137,60 +119,6 @@ func DeleteClusterObject(deployContext *chetypes.DeployContext, name string, obj
return DeleteByKeyWithClient(client, key, objectMeta) return DeleteByKeyWithClient(client, key, objectMeta)
} }
// Updates object.
// Returns true if object is up to date otherwiser return false
func UpdateWithClient(client client.Client, deployContext *chetypes.DeployContext, actual client.Object, blueprint client.Object, diffOpts ...cmp.Option) (bool, error) {
actualMeta, ok := actual.(metav1.Object)
if !ok {
return false, fmt.Errorf("object %T is not a metav1.Object. Cannot sync it", actualMeta)
}
diff := cmp.Diff(actual, blueprint, diffOpts...)
if len(diff) > 0 {
// don't print difference if there are no diffOpts mainly to avoid huge output
if len(diffOpts) != 0 {
fmt.Printf("Difference:\n%s", diff)
}
if isUpdateUsingDeleteCreate(actual.GetObjectKind().GroupVersionKind().Kind) {
done, err := doDeleteIgnoreIfNotFound(context.TODO(), client, actual)
if !done {
return false, err
}
return CreateWithClient(client, deployContext, blueprint, false)
} else {
err := setOwnerReferenceIfNeeded(deployContext, blueprint)
if err != nil {
return false, err
}
// to be able to update, we need to set the resource version of the object that we know of
blueprint.(metav1.Object).SetResourceVersion(actualMeta.GetResourceVersion())
err = client.Update(context.TODO(), blueprint)
syncLog.Info("Object updated", "namespace", actual.GetNamespace(), "kind", GetObjectType(actual), "name", actual.GetName())
return false, err
}
}
return true, nil
}
func CreateWithClient(client client.Client, deployContext *chetypes.DeployContext, blueprint client.Object, returnTrueIfAlreadyExists bool) (bool, error) {
err := setOwnerReferenceIfNeeded(deployContext, blueprint)
if err != nil {
return false, err
}
err = client.Create(context.TODO(), blueprint)
if err == nil {
syncLog.Info("Object created", "namespace", blueprint.GetNamespace(), "kind", GetObjectType(blueprint), "name", blueprint.GetName())
return true, nil
} else if errors.IsAlreadyExists(err) {
return returnTrueIfAlreadyExists, nil
} else {
return false, err
}
}
func DeleteByKeyWithClient(cli client.Client, key client.ObjectKey, objectMeta client.Object) (bool, error) { func DeleteByKeyWithClient(cli client.Client, key client.ObjectKey, objectMeta client.Object) (bool, error) {
runtimeObject, ok := objectMeta.(runtime.Object) runtimeObject, ok := objectMeta.(runtime.Object)
if !ok { if !ok {
@ -198,7 +126,7 @@ func DeleteByKeyWithClient(cli client.Client, key client.ObjectKey, objectMeta c
} }
actual := runtimeObject.DeepCopyObject().(client.Object) actual := runtimeObject.DeepCopyObject().(client.Object)
exists, err := GetWithClient(cli, key, actual) exists, err := doGet(context.TODO(), cli, key, actual)
if !exists { if !exists {
return true, nil return true, nil
} else if err != nil { } else if err != nil {
@ -208,17 +136,6 @@ func DeleteByKeyWithClient(cli client.Client, key client.ObjectKey, objectMeta c
return doDeleteIgnoreIfNotFound(context.TODO(), cli, actual) return doDeleteIgnoreIfNotFound(context.TODO(), cli, actual)
} }
func GetWithClient(client client.Client, key client.ObjectKey, object client.Object) (bool, error) {
err := client.Get(context.TODO(), key, object)
if err == nil {
return true, nil
} else if errors.IsNotFound(err) {
return false, nil
} else {
return false, err
}
}
func isUpdateUsingDeleteCreate(kind string) bool { func isUpdateUsingDeleteCreate(kind string) bool {
return "Service" == kind || "Ingress" == kind || "Route" == kind || "Job" == kind || "Secret" == kind return "Service" == kind || "Ingress" == kind || "Route" == kind || "Job" == kind || "Secret" == kind
} }
@ -255,7 +172,13 @@ func GetObjectType(obj interface{}) string {
// DeleteIgnoreIfNotFound deletes object. // DeleteIgnoreIfNotFound deletes object.
// Returns nil if object deleted or not found otherwise returns error. // Returns nil if object deleted or not found otherwise returns error.
func DeleteIgnoreIfNotFound(context context.Context, cli client.Client, key client.ObjectKey, blueprint client.Object) error { // Return error if object cannot be deleted otherwise returns nil.
func DeleteIgnoreIfNotFound(
context context.Context,
cli client.Client,
key client.ObjectKey,
blueprint client.Object,
) error {
runtimeObj, ok := blueprint.(runtime.Object) runtimeObj, ok := blueprint.(runtime.Object)
if !ok { if !ok {
return fmt.Errorf("object %T is not a runtime.Object. Cannot sync it", runtimeObj) return fmt.Errorf("object %T is not a runtime.Object. Cannot sync it", runtimeObj)
@ -273,9 +196,14 @@ func DeleteIgnoreIfNotFound(context context.Context, cli client.Client, key clie
} }
// doCreate creates object. // doCreate creates object.
// Returns true if object created otherwise returns false. // Return error if object cannot be created otherwise returns nil.
// Throws error if object cannot be created or already exists otherwise returns nil. func doCreate(
func doCreate(context context.Context, client client.Client, deployContext *chetypes.DeployContext, blueprint client.Object) (bool, error) { context context.Context,
client client.Client,
deployContext *chetypes.DeployContext,
blueprint client.Object,
returnTrueIfAlreadyExists bool,
) (bool, error) {
err := setOwnerReferenceIfNeeded(deployContext, blueprint) err := setOwnerReferenceIfNeeded(deployContext, blueprint)
if err != nil { if err != nil {
return false, err return false, err
@ -285,6 +213,8 @@ func doCreate(context context.Context, client client.Client, deployContext *chet
if err == nil { if err == nil {
syncLog.Info("Object created", "namespace", blueprint.GetNamespace(), "kind", GetObjectType(blueprint), "name", blueprint.GetName()) syncLog.Info("Object created", "namespace", blueprint.GetNamespace(), "kind", GetObjectType(blueprint), "name", blueprint.GetName())
return true, nil return true, nil
} else if errors.IsAlreadyExists(err) {
return returnTrueIfAlreadyExists, nil
} else { } else {
return false, err return false, err
} }
@ -293,7 +223,11 @@ func doCreate(context context.Context, client client.Client, deployContext *chet
// doDeleteIgnoreIfNotFound deletes object. // doDeleteIgnoreIfNotFound deletes object.
// Returns true if object deleted or not found otherwise returns false. // Returns true if object deleted or not found otherwise returns false.
// Returns error if object cannot be deleted otherwise returns nil. // Returns error if object cannot be deleted otherwise returns nil.
func doDeleteIgnoreIfNotFound(context context.Context, cli client.Client, actual client.Object) (bool, error) { func doDeleteIgnoreIfNotFound(
context context.Context,
cli client.Client,
actual client.Object,
) (bool, error) {
err := cli.Delete(context, actual) err := cli.Delete(context, actual)
if err == nil { if err == nil {
if errors.IsNotFound(err) { if errors.IsNotFound(err) {
@ -310,7 +244,12 @@ func doDeleteIgnoreIfNotFound(context context.Context, cli client.Client, actual
// doGet gets object. // doGet gets object.
// Returns true if object exists otherwise returns false. // Returns true if object exists otherwise returns false.
// Returns error if object cannot be retrieved otherwise returns nil. // Returns error if object cannot be retrieved otherwise returns nil.
func doGet(context context.Context, cli client.Client, key client.ObjectKey, object client.Object) (bool, error) { func doGet(
context context.Context,
cli client.Client,
key client.ObjectKey,
object client.Object,
) (bool, error) {
err := cli.Get(context, key, object) err := cli.Get(context, key, object)
if err == nil { if err == nil {
return true, nil return true, nil
@ -320,3 +259,49 @@ func doGet(context context.Context, cli client.Client, key client.ObjectKey, obj
return false, err return false, err
} }
} }
// doUpdate updates object.
// Returns true if object is up-to-date otherwise return false
func doUpdate(
cli client.Client,
deployContext *chetypes.DeployContext,
actual client.Object,
blueprint client.Object,
diffOpts ...cmp.Option,
) (bool, error) {
actualMeta, ok := actual.(metav1.Object)
if !ok {
return false, fmt.Errorf("object %T is not a metav1.Object. Cannot sync it", actualMeta)
}
diff := cmp.Diff(actual, blueprint, diffOpts...)
if len(diff) > 0 {
// don't print difference if there are no diffOpts mainly to avoid huge output
if len(diffOpts) != 0 {
fmt.Printf("Difference:\n%s", diff)
}
if isUpdateUsingDeleteCreate(actual.GetObjectKind().GroupVersionKind().Kind) {
done, err := doDeleteIgnoreIfNotFound(context.TODO(), cli, actual)
if !done {
return false, err
}
return doCreate(context.TODO(), cli, deployContext, blueprint, false)
} else {
err := setOwnerReferenceIfNeeded(deployContext, blueprint)
if err != nil {
return false, err
}
// to be able to update, we need to set the resource version of the object that we know of
blueprint.(metav1.Object).SetResourceVersion(actualMeta.GetResourceVersion())
err = cli.Update(context.TODO(), blueprint)
if err == nil {
syncLog.Info("Object updated", "namespace", actual.GetNamespace(), "kind", GetObjectType(actual), "name", actual.GetName())
}
return false, err
}
}
return true, nil
}

View File

@ -15,6 +15,8 @@ package deploy
import ( import (
"context" "context"
"github.com/stretchr/testify/assert"
chev2 "github.com/eclipse-che/che-operator/api/v2" chev2 "github.com/eclipse-che/che-operator/api/v2"
"github.com/eclipse-che/che-operator/pkg/common/chetypes" "github.com/eclipse-che/che-operator/pkg/common/chetypes"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
@ -74,68 +76,28 @@ func TestGet(t *testing.T) {
} }
} }
func TestCreate(t *testing.T) { func TestCreateIgnoreIfExistsShouldReturnTrueIfObjectCreated(t *testing.T) {
cli, deployContext := initDeployContext() cli, deployContext := initDeployContext()
done, err := Create(deployContext, testObj.DeepCopy()) done, err := CreateIgnoreIfExists(deployContext, testObj.DeepCopy())
if err != nil { assert.NoError(t, err)
t.Fatalf("Failed to create object: %v", err) assert.True(t, done)
}
if !done {
t.Fatalf("Object has not been created")
}
actual := &corev1.Secret{} actual := &corev1.Secret{}
err = cli.Get(context.TODO(), testKey, actual) err = cli.Get(context.TODO(), testKey, actual)
if err != nil && !errors.IsNotFound(err) { assert.NoError(t, err)
t.Fatalf("Failed to get object: %v", err) assert.NotNil(t, actual)
} }
if actual == nil { func TestCreateIgnoreIfExistsShouldReturnTrueIfObjectExist(t *testing.T) {
t.Fatalf("Object not found")
}
}
func TestCreateIfNotExistsShouldReturnTrueIfObjectCreated(t *testing.T) {
cli, deployContext := initDeployContext()
done, err := CreateIfNotExists(deployContext, testObj.DeepCopy())
if err != nil {
t.Fatalf("Failed to create object: %v", err)
}
if !done {
t.Fatalf("Object has not been created")
}
actual := &corev1.Secret{}
err = cli.Get(context.TODO(), testKey, actual)
if err != nil && !errors.IsNotFound(err) {
t.Fatalf("Failed to get object: %v", err)
}
if actual == nil {
t.Fatalf("Object not found")
}
}
func TestCreateIfNotExistsShouldReturnFalseIfObjectExist(t *testing.T) {
cli, deployContext := initDeployContext() cli, deployContext := initDeployContext()
err := cli.Create(context.TODO(), testObj.DeepCopy()) err := cli.Create(context.TODO(), testObj.DeepCopy())
if err != nil { assert.NoError(t, err)
t.Fatalf("Failed to create object: %v", err)
}
isCreated, err := CreateIfNotExists(deployContext, testObj.DeepCopy()) done, err := CreateIgnoreIfExists(deployContext, testObj.DeepCopy())
if err != nil { assert.NoError(t, err)
t.Fatalf("Failed to create object: %v", err) assert.True(t, done)
}
if isCreated {
t.Fatalf("Object has been created")
}
} }
func TestUpdate(t *testing.T) { func TestUpdate(t *testing.T) {
@ -152,7 +114,7 @@ func TestUpdate(t *testing.T) {
t.Fatalf("Failed to get object: %v", err) t.Fatalf("Failed to get object: %v", err)
} }
_, err = UpdateWithClient(cli, deployContext, actual, testObjLabeled.DeepCopy(), cmp.Options{}) _, err = doUpdate(cli, deployContext, actual, testObjLabeled.DeepCopy(), cmp.Options{})
if err != nil { if err != nil {
t.Fatalf("Failed to update object: %v", err) t.Fatalf("Failed to update object: %v", err)
} }

View File

@ -94,8 +94,7 @@ func (c *CertificatesReconciler) syncTrustStoreConfigMapToCluster(ctx *chetypes.
if !exists { if !exists {
// We have to create an empty config map with the specific labels // We have to create an empty config map with the specific labels
done, err := deploy.Create(ctx, configMapSpec) return deploy.CreateIgnoreIfExists(ctx, configMapSpec)
return done, err
} }
if actual.ObjectMeta.Labels[injector] != "true" || if actual.ObjectMeta.Labels[injector] != "true" ||