Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: verify DeploymentConfig API when installing keycloak using Template #1329

Merged
merged 3 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions controllers/argocd/keycloak.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func getKeycloakContainerImage(cr *argoproj.ArgoCD) string {

if img == "" {
img = common.ArgoCDKeycloakImage
if IsTemplateAPIAvailable() {
if CanUseKeycloakWithTemplate() {
img = common.ArgoCDKeycloakImageForOpenShift
}
defaultImg = true
Expand All @@ -123,7 +123,7 @@ func getKeycloakContainerImage(cr *argoproj.ArgoCD) string {

if tag == "" {
tag = common.ArgoCDKeycloakVersion
if IsTemplateAPIAvailable() {
if CanUseKeycloakWithTemplate() {
tag = common.ArgoCDKeycloakVersionForOpenShift
}
defaultTag = true
Expand Down Expand Up @@ -910,7 +910,7 @@ func createRealmConfig(cfg *keycloakConfig) ([]byte, error) {

// Add OpenShift-v4 as Identity Provider only for OpenShift environment.
// No Identity Provider is configured by default for non-openshift environments.
if IsTemplateAPIAvailable() {
if CanUseKeycloakWithTemplate() {
baseURL := "https://kubernetes.default.svc.cluster.local"
if isProxyCluster() {
baseURL = getOpenShiftAPIURL()
Expand Down Expand Up @@ -1005,7 +1005,7 @@ func (r *ReconcileArgoCD) updateArgoCDConfiguration(cr *argoproj.ArgoCD, kRouteU
}

// Create openshift OAuthClient
if IsTemplateAPIAvailable() {
if CanUseKeycloakWithTemplate() {
oAuthClient := &oauthv1.OAuthClient{
TypeMeta: metav1.TypeMeta{
Kind: "OAuthClient",
Expand Down Expand Up @@ -1128,7 +1128,7 @@ func handleKeycloakPodDeletion(dc *appsv1.DeploymentConfig) error {
func (r *ReconcileArgoCD) reconcileKeycloakConfiguration(cr *argoproj.ArgoCD) error {

// TemplateAPI is available, Install keycloak using openshift templates.
if IsTemplateAPIAvailable() {
if CanUseKeycloakWithTemplate() {
err := r.reconcileKeycloakForOpenShift(cr)
if err != nil {
return err
Expand All @@ -1146,7 +1146,7 @@ func (r *ReconcileArgoCD) reconcileKeycloakConfiguration(cr *argoproj.ArgoCD) er
func deleteKeycloakConfiguration(cr *argoproj.ArgoCD) error {

// If SSO is installed using OpenShift templates.
if IsTemplateAPIAvailable() {
if CanUseKeycloakWithTemplate() {
err := deleteKeycloakConfigForOpenShift(cr)
if err != nil {
return err
Expand Down
45 changes: 27 additions & 18 deletions controllers/argocd/keycloak_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,14 @@ func TestKeycloakContainerImage(t *testing.T) {

defer removeTemplateAPI()
tests := []struct {
name string
setEnvVarFunc func(*testing.T, string)
envVar string
argoCD *argoproj.ArgoCD
updateCrFunc func(cr *argoproj.ArgoCD)
templateAPIFound bool
wantContainerImage string
name string
setEnvVarFunc func(*testing.T, string)
envVar string
argoCD *argoproj.ArgoCD
updateCrFunc func(cr *argoproj.ArgoCD)
templateAPIFound bool
deploymentConfigAPIFound bool
wantContainerImage string
}{
{
name: "no .spec.sso, no ArgoCDKeycloakImageEnvName env var set",
Expand All @@ -101,9 +102,10 @@ func TestKeycloakContainerImage(t *testing.T) {
Provider: argoproj.SSOProviderTypeKeycloak,
}
}),
updateCrFunc: nil,
templateAPIFound: false,
wantContainerImage: "quay.io/keycloak/keycloak@sha256:64fb81886fde61dee55091e6033481fa5ccdac62ae30a4fd29b54eb5e97df6a9",
updateCrFunc: nil,
templateAPIFound: false,
deploymentConfigAPIFound: false,
wantContainerImage: "quay.io/keycloak/keycloak@sha256:64fb81886fde61dee55091e6033481fa5ccdac62ae30a4fd29b54eb5e97df6a9",
},
{
name: "no .spec.sso, no ArgoCDKeycloakImageEnvName env var set - for OCP",
Expand All @@ -114,9 +116,10 @@ func TestKeycloakContainerImage(t *testing.T) {
Provider: argoproj.SSOProviderTypeKeycloak,
}
}),
updateCrFunc: nil,
templateAPIFound: true,
wantContainerImage: "registry.redhat.io/rh-sso-7/sso76-openshift-rhel8@sha256:ec9f60018694dcc5d431ba47d5536b761b71cb3f66684978fe6bb74c157679ac",
updateCrFunc: nil,
templateAPIFound: true,
deploymentConfigAPIFound: true,
wantContainerImage: "registry.redhat.io/rh-sso-7/sso76-openshift-rhel8@sha256:ec9f60018694dcc5d431ba47d5536b761b71cb3f66684978fe6bb74c157679ac",
},
{
name: "ArgoCDKeycloakImageEnvName env var set",
Expand All @@ -129,9 +132,10 @@ func TestKeycloakContainerImage(t *testing.T) {
Provider: argoproj.SSOProviderTypeKeycloak,
}
}),
updateCrFunc: nil,
templateAPIFound: true,
wantContainerImage: "envImage:latest",
updateCrFunc: nil,
templateAPIFound: true,
deploymentConfigAPIFound: true,
wantContainerImage: "envImage:latest",
},
{
name: "both cr.spec.sso.keycloak.Image and ArgoCDKeycloakImageEnvName are set",
Expand All @@ -153,14 +157,16 @@ func TestKeycloakContainerImage(t *testing.T) {
},
}
},
templateAPIFound: true,
wantContainerImage: "crImage:crVersion",
templateAPIFound: true,
deploymentConfigAPIFound: true,
wantContainerImage: "crImage:crVersion",
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
templateAPIFound = test.templateAPIFound
deploymentConfigAPIFound = test.deploymentConfigAPIFound

if test.setEnvVarFunc != nil {
test.setEnvVarFunc(t, test.envVar)
Expand Down Expand Up @@ -244,6 +250,8 @@ func TestNewKeycloakTemplate_testKeycloakContainer(t *testing.T) {
// For OpenShift Container Platform.
t.Setenv(common.ArgoCDKeycloakImageEnvName, "")
templateAPIFound = true
deploymentConfigAPIFound = true

defer removeTemplateAPI()

a := makeTestArgoCD()
Expand Down Expand Up @@ -496,4 +504,5 @@ func TestKeycloak_NodeLabelSelector(t *testing.T) {

func removeTemplateAPI() {
templateAPIFound = false
deploymentConfigAPIFound = false
}
36 changes: 27 additions & 9 deletions controllers/argocd/sso.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"errors"
"fmt"

deploymentConfig "github.com/openshift/api/apps/v1"
template "github.com/openshift/api/template/v1"
apiErrors "k8s.io/apimachinery/pkg/api/errors"

Expand All @@ -33,22 +34,29 @@ const (
)

var (
templateAPIFound = false
ssoConfigLegalStatus string
templateAPIFound = false
deploymentConfigAPIFound = false
ssoConfigLegalStatus string
)

// IsTemplateAPIAvailable returns true if the template API is present.
func IsTemplateAPIAvailable() bool {
return templateAPIFound
// CanUseKeycloakWithTemplate checks if the required APIs are available to
// manage a Keycloak instance using Templates.
func CanUseKeycloakWithTemplate() bool {
return templateAPIFound && deploymentConfigAPIFound
}

// verifyTemplateAPI will verify that the template API is present.
func verifyTemplateAPI() error {
found, err := argoutil.VerifyAPI(template.GroupVersion.Group, template.GroupVersion.Version)
func verifyKeycloakTemplateAPIs() error {
var err error
deploymentConfigAPIFound, err = argoutil.VerifyAPI(deploymentConfig.GroupVersion.Group, deploymentConfig.GroupVersion.Version)
if err != nil {
return err
}
templateAPIFound = found

templateAPIFound, err = argoutil.VerifyAPI(template.GroupVersion.Group, template.GroupVersion.Version)
if err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -115,6 +123,16 @@ func (r *ReconcileArgoCD) reconcileSSO(cr *argoproj.ArgoCD) error {
_ = r.reconcileStatusSSO(cr)
return err
}

// DeploymentConfig API is being deprecated with OpenShift 4.14. Users who wish to
// install Keycloak using Template should enable the DeploymentConfig API.
if templateAPIFound && !deploymentConfigAPIFound {
ssoConfigLegalStatus = ssoLegalFailed
if err := r.reconcileStatusSSO(cr); err != nil {
return err
}
return fmt.Errorf("cannot manage Keycloak using Template since the DeploymentConfig API is not found")
}
}

// case 4
Expand Down
32 changes: 32 additions & 0 deletions controllers/argocd/sso_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ import (
logf "sigs.k8s.io/controller-runtime/pkg/log"

argoproj "github.com/argoproj-labs/argocd-operator/api/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
)

func TestReconcile_testKeycloakTemplateInstance(t *testing.T) {
logf.SetLogger(ZapLogger(true))
a := makeTestArgoCDForKeycloak()

templateAPIFound = true
deploymentConfigAPIFound = true

resObjs := []client.Object{a}
subresObjs := []client.Object{a}
Expand Down Expand Up @@ -263,6 +265,36 @@ func TestReconcile_testKeycloakK8sInstance(t *testing.T) {
assert.NoError(t, r.reconcileSSO(a))
}

func TestReconcile_KeycloakTemplateWithoutDeploymentConfig(t *testing.T) {
logf.SetLogger(ZapLogger(true))
a := makeTestArgoCDForKeycloak()

// Cluster has Template API but no DeploymentConfig API
templateAPIFound = true
deploymentConfigAPIFound = false
defer removeTemplateAPI()

resObjs := []client.Object{a}
subresObjs := []client.Object{a}
runtimeObjs := []runtime.Object{}
sch := makeTestReconcilerScheme(argoproj.AddToScheme, templatev1.Install, oappsv1.Install, routev1.Install)
cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
r := makeTestReconciler(cl, sch)

assert.NoError(t, createNamespace(r, a.Namespace, ""))

err := r.reconcileSSO(a)
assert.NotNil(t, err)
expectedErrMsg := "cannot manage Keycloak using Template since the DeploymentConfig API is not found"
assert.Equal(t, err.Error(), expectedErrMsg)

// Verify that the Template instance is not created.
templateInstance := &templatev1.TemplateInstance{}
err = r.Client.Get(context.TODO(), types.NamespacedName{Name: "rhsso", Namespace: a.Namespace}, templateInstance)
assert.NotNil(t, err)
assert.True(t, apierrors.IsNotFound(err))
}

func TestReconcile_testKeycloakInstanceResources(t *testing.T) {
logf.SetLogger(ZapLogger(true))
a := makeTestArgoCDForKeycloak()
Expand Down
2 changes: 1 addition & 1 deletion controllers/argocd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func (r *ReconcileArgoCD) reconcileStatusDex(cr *argoproj.ArgoCD) error {
func (r *ReconcileArgoCD) reconcileStatusKeycloak(cr *argoproj.ArgoCD) error {
status := "Unknown"

if IsTemplateAPIAvailable() {
if CanUseKeycloakWithTemplate() {
// keycloak is installed using OpenShift templates.
dc := &oappsv1.DeploymentConfig{
ObjectMeta: metav1.ObjectMeta{
Expand Down
1 change: 1 addition & 0 deletions controllers/argocd/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func TestReconcileArgoCD_reconcileStatusKeycloak_OpenShift(t *testing.T) {

assert.NoError(t, oappsv1.Install(r.Scheme))
templateAPIFound = true
deploymentConfigAPIFound = true
defer removeTemplateAPI()

dc := getKeycloakDeploymentConfigTemplate(a)
Expand Down
4 changes: 2 additions & 2 deletions controllers/argocd/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ func InspectCluster() error {
return err
}

if err := verifyTemplateAPI(); err != nil {
if err := verifyKeycloakTemplateAPIs(); err != nil {
return err
}

Expand Down Expand Up @@ -1078,7 +1078,7 @@ func (r *ReconcileArgoCD) setResourceWatches(bldr *builder.Builder, clusterResou
bldr.Owns(&monitoringv1.ServiceMonitor{})
}

if IsTemplateAPIAvailable() {
if CanUseKeycloakWithTemplate() {
// Watch for the changes to Deployment Config
bldr.Owns(&oappsv1.DeploymentConfig{}, builder.WithPredicates(deploymentConfigPred))

Expand Down
5 changes: 4 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,8 @@ func main() {
}

// Setup Schemes for SSO if template instance is available.
if argocd.IsTemplateAPIAvailable() {
if argocd.CanUseKeycloakWithTemplate() {
chetan-rns marked this conversation as resolved.
Show resolved Hide resolved
setupLog.Info("Keycloak instance can be managed using OpenShift Template")
chetan-rns marked this conversation as resolved.
Show resolved Hide resolved
if err := templatev1.Install(mgr.GetScheme()); err != nil {
setupLog.Error(err, "")
os.Exit(1)
Expand All @@ -240,6 +241,8 @@ func main() {
setupLog.Error(err, "")
os.Exit(1)
}
} else {
setupLog.Info("Keycloak instance cannot be managed using OpenShift Template, as DeploymentConfig/Template API is not present")
}

if err = (&argocd.ReconcileArgoCD{
Expand Down
Loading