Skip to content

Commit 5dc1abe

Browse files
authored
fix: verify DeploymentConfig API when installing keycloak using Template (#1329)
* fix: verify DeploymentConfig API when installing keycloak using Template Signed-off-by: Chetan Banavikalmutt <[email protected]> * return an error if the DeploymentConfig API is not present on OCP Signed-off-by: Chetan Banavikalmutt <[email protected]> * log when the Keycloak instance can't be managed using Template Signed-off-by: Chetan Banavikalmutt <[email protected]> --------- Signed-off-by: Chetan Banavikalmutt <[email protected]>
1 parent 4f7b18a commit 5dc1abe

File tree

8 files changed

+100
-37
lines changed

8 files changed

+100
-37
lines changed

controllers/argocd/keycloak.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func getKeycloakContainerImage(cr *argoproj.ArgoCD) string {
111111

112112
if img == "" {
113113
img = common.ArgoCDKeycloakImage
114-
if IsTemplateAPIAvailable() {
114+
if CanUseKeycloakWithTemplate() {
115115
img = common.ArgoCDKeycloakImageForOpenShift
116116
}
117117
defaultImg = true
@@ -123,7 +123,7 @@ func getKeycloakContainerImage(cr *argoproj.ArgoCD) string {
123123

124124
if tag == "" {
125125
tag = common.ArgoCDKeycloakVersion
126-
if IsTemplateAPIAvailable() {
126+
if CanUseKeycloakWithTemplate() {
127127
tag = common.ArgoCDKeycloakVersionForOpenShift
128128
}
129129
defaultTag = true
@@ -910,7 +910,7 @@ func createRealmConfig(cfg *keycloakConfig) ([]byte, error) {
910910

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

10071007
// Create openshift OAuthClient
1008-
if IsTemplateAPIAvailable() {
1008+
if CanUseKeycloakWithTemplate() {
10091009
oAuthClient := &oauthv1.OAuthClient{
10101010
TypeMeta: metav1.TypeMeta{
10111011
Kind: "OAuthClient",
@@ -1128,7 +1128,7 @@ func handleKeycloakPodDeletion(dc *appsv1.DeploymentConfig) error {
11281128
func (r *ReconcileArgoCD) reconcileKeycloakConfiguration(cr *argoproj.ArgoCD) error {
11291129

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

11481148
// If SSO is installed using OpenShift templates.
1149-
if IsTemplateAPIAvailable() {
1149+
if CanUseKeycloakWithTemplate() {
11501150
err := deleteKeycloakConfigForOpenShift(cr)
11511151
if err != nil {
11521152
return err

controllers/argocd/keycloak_test.go

+27-18
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,14 @@ func TestKeycloakContainerImage(t *testing.T) {
8484

8585
defer removeTemplateAPI()
8686
tests := []struct {
87-
name string
88-
setEnvVarFunc func(*testing.T, string)
89-
envVar string
90-
argoCD *argoproj.ArgoCD
91-
updateCrFunc func(cr *argoproj.ArgoCD)
92-
templateAPIFound bool
93-
wantContainerImage string
87+
name string
88+
setEnvVarFunc func(*testing.T, string)
89+
envVar string
90+
argoCD *argoproj.ArgoCD
91+
updateCrFunc func(cr *argoproj.ArgoCD)
92+
templateAPIFound bool
93+
deploymentConfigAPIFound bool
94+
wantContainerImage string
9495
}{
9596
{
9697
name: "no .spec.sso, no ArgoCDKeycloakImageEnvName env var set",
@@ -101,9 +102,10 @@ func TestKeycloakContainerImage(t *testing.T) {
101102
Provider: argoproj.SSOProviderTypeKeycloak,
102103
}
103104
}),
104-
updateCrFunc: nil,
105-
templateAPIFound: false,
106-
wantContainerImage: "quay.io/keycloak/keycloak@sha256:64fb81886fde61dee55091e6033481fa5ccdac62ae30a4fd29b54eb5e97df6a9",
105+
updateCrFunc: nil,
106+
templateAPIFound: false,
107+
deploymentConfigAPIFound: false,
108+
wantContainerImage: "quay.io/keycloak/keycloak@sha256:64fb81886fde61dee55091e6033481fa5ccdac62ae30a4fd29b54eb5e97df6a9",
107109
},
108110
{
109111
name: "no .spec.sso, no ArgoCDKeycloakImageEnvName env var set - for OCP",
@@ -114,9 +116,10 @@ func TestKeycloakContainerImage(t *testing.T) {
114116
Provider: argoproj.SSOProviderTypeKeycloak,
115117
}
116118
}),
117-
updateCrFunc: nil,
118-
templateAPIFound: true,
119-
wantContainerImage: "registry.redhat.io/rh-sso-7/sso76-openshift-rhel8@sha256:ec9f60018694dcc5d431ba47d5536b761b71cb3f66684978fe6bb74c157679ac",
119+
updateCrFunc: nil,
120+
templateAPIFound: true,
121+
deploymentConfigAPIFound: true,
122+
wantContainerImage: "registry.redhat.io/rh-sso-7/sso76-openshift-rhel8@sha256:ec9f60018694dcc5d431ba47d5536b761b71cb3f66684978fe6bb74c157679ac",
120123
},
121124
{
122125
name: "ArgoCDKeycloakImageEnvName env var set",
@@ -129,9 +132,10 @@ func TestKeycloakContainerImage(t *testing.T) {
129132
Provider: argoproj.SSOProviderTypeKeycloak,
130133
}
131134
}),
132-
updateCrFunc: nil,
133-
templateAPIFound: true,
134-
wantContainerImage: "envImage:latest",
135+
updateCrFunc: nil,
136+
templateAPIFound: true,
137+
deploymentConfigAPIFound: true,
138+
wantContainerImage: "envImage:latest",
135139
},
136140
{
137141
name: "both cr.spec.sso.keycloak.Image and ArgoCDKeycloakImageEnvName are set",
@@ -153,14 +157,16 @@ func TestKeycloakContainerImage(t *testing.T) {
153157
},
154158
}
155159
},
156-
templateAPIFound: true,
157-
wantContainerImage: "crImage:crVersion",
160+
templateAPIFound: true,
161+
deploymentConfigAPIFound: true,
162+
wantContainerImage: "crImage:crVersion",
158163
},
159164
}
160165

161166
for _, test := range tests {
162167
t.Run(test.name, func(t *testing.T) {
163168
templateAPIFound = test.templateAPIFound
169+
deploymentConfigAPIFound = test.deploymentConfigAPIFound
164170

165171
if test.setEnvVarFunc != nil {
166172
test.setEnvVarFunc(t, test.envVar)
@@ -244,6 +250,8 @@ func TestNewKeycloakTemplate_testKeycloakContainer(t *testing.T) {
244250
// For OpenShift Container Platform.
245251
t.Setenv(common.ArgoCDKeycloakImageEnvName, "")
246252
templateAPIFound = true
253+
deploymentConfigAPIFound = true
254+
247255
defer removeTemplateAPI()
248256

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

497505
func removeTemplateAPI() {
498506
templateAPIFound = false
507+
deploymentConfigAPIFound = false
499508
}

controllers/argocd/sso.go

+27-9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"errors"
1919
"fmt"
2020

21+
deploymentConfig "github.com/openshift/api/apps/v1"
2122
template "github.com/openshift/api/template/v1"
2223
apiErrors "k8s.io/apimachinery/pkg/api/errors"
2324

@@ -33,22 +34,29 @@ const (
3334
)
3435

3536
var (
36-
templateAPIFound = false
37-
ssoConfigLegalStatus string
37+
templateAPIFound = false
38+
deploymentConfigAPIFound = false
39+
ssoConfigLegalStatus string
3840
)
3941

40-
// IsTemplateAPIAvailable returns true if the template API is present.
41-
func IsTemplateAPIAvailable() bool {
42-
return templateAPIFound
42+
// CanUseKeycloakWithTemplate checks if the required APIs are available to
43+
// manage a Keycloak instance using Templates.
44+
func CanUseKeycloakWithTemplate() bool {
45+
return templateAPIFound && deploymentConfigAPIFound
4346
}
4447

45-
// verifyTemplateAPI will verify that the template API is present.
46-
func verifyTemplateAPI() error {
47-
found, err := argoutil.VerifyAPI(template.GroupVersion.Group, template.GroupVersion.Version)
48+
func verifyKeycloakTemplateAPIs() error {
49+
var err error
50+
deploymentConfigAPIFound, err = argoutil.VerifyAPI(deploymentConfig.GroupVersion.Group, deploymentConfig.GroupVersion.Version)
4851
if err != nil {
4952
return err
5053
}
51-
templateAPIFound = found
54+
55+
templateAPIFound, err = argoutil.VerifyAPI(template.GroupVersion.Group, template.GroupVersion.Version)
56+
if err != nil {
57+
return err
58+
}
59+
5260
return nil
5361
}
5462

@@ -115,6 +123,16 @@ func (r *ReconcileArgoCD) reconcileSSO(cr *argoproj.ArgoCD) error {
115123
_ = r.reconcileStatusSSO(cr)
116124
return err
117125
}
126+
127+
// DeploymentConfig API is being deprecated with OpenShift 4.14. Users who wish to
128+
// install Keycloak using Template should enable the DeploymentConfig API.
129+
if templateAPIFound && !deploymentConfigAPIFound {
130+
ssoConfigLegalStatus = ssoLegalFailed
131+
if err := r.reconcileStatusSSO(cr); err != nil {
132+
return err
133+
}
134+
return fmt.Errorf("cannot manage Keycloak using Template since the DeploymentConfig API is not found")
135+
}
118136
}
119137

120138
// case 4

controllers/argocd/sso_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ import (
3333
logf "sigs.k8s.io/controller-runtime/pkg/log"
3434

3535
argoproj "github.com/argoproj-labs/argocd-operator/api/v1beta1"
36+
apierrors "k8s.io/apimachinery/pkg/api/errors"
3637
)
3738

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

4243
templateAPIFound = true
44+
deploymentConfigAPIFound = true
4345

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

268+
func TestReconcile_KeycloakTemplateWithoutDeploymentConfig(t *testing.T) {
269+
logf.SetLogger(ZapLogger(true))
270+
a := makeTestArgoCDForKeycloak()
271+
272+
// Cluster has Template API but no DeploymentConfig API
273+
templateAPIFound = true
274+
deploymentConfigAPIFound = false
275+
defer removeTemplateAPI()
276+
277+
resObjs := []client.Object{a}
278+
subresObjs := []client.Object{a}
279+
runtimeObjs := []runtime.Object{}
280+
sch := makeTestReconcilerScheme(argoproj.AddToScheme, templatev1.Install, oappsv1.Install, routev1.Install)
281+
cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
282+
r := makeTestReconciler(cl, sch)
283+
284+
assert.NoError(t, createNamespace(r, a.Namespace, ""))
285+
286+
err := r.reconcileSSO(a)
287+
assert.NotNil(t, err)
288+
expectedErrMsg := "cannot manage Keycloak using Template since the DeploymentConfig API is not found"
289+
assert.Equal(t, err.Error(), expectedErrMsg)
290+
291+
// Verify that the Template instance is not created.
292+
templateInstance := &templatev1.TemplateInstance{}
293+
err = r.Client.Get(context.TODO(), types.NamespacedName{Name: "rhsso", Namespace: a.Namespace}, templateInstance)
294+
assert.NotNil(t, err)
295+
assert.True(t, apierrors.IsNotFound(err))
296+
}
297+
266298
func TestReconcile_testKeycloakInstanceResources(t *testing.T) {
267299
logf.SetLogger(ZapLogger(true))
268300
a := makeTestArgoCDForKeycloak()

controllers/argocd/status.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func (r *ReconcileArgoCD) reconcileStatusDex(cr *argoproj.ArgoCD) error {
130130
func (r *ReconcileArgoCD) reconcileStatusKeycloak(cr *argoproj.ArgoCD) error {
131131
status := "Unknown"
132132

133-
if IsTemplateAPIAvailable() {
133+
if CanUseKeycloakWithTemplate() {
134134
// keycloak is installed using OpenShift templates.
135135
dc := &oappsv1.DeploymentConfig{
136136
ObjectMeta: metav1.ObjectMeta{

controllers/argocd/status_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ func TestReconcileArgoCD_reconcileStatusKeycloak_OpenShift(t *testing.T) {
6767

6868
assert.NoError(t, oappsv1.Install(r.Scheme))
6969
templateAPIFound = true
70+
deploymentConfigAPIFound = true
7071
defer removeTemplateAPI()
7172

7273
dc := getKeycloakDeploymentConfigTemplate(a)

controllers/argocd/util.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ func InspectCluster() error {
616616
return err
617617
}
618618

619-
if err := verifyTemplateAPI(); err != nil {
619+
if err := verifyKeycloakTemplateAPIs(); err != nil {
620620
return err
621621
}
622622

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

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

main.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,8 @@ func main() {
227227
}
228228

229229
// Setup Schemes for SSO if template instance is available.
230-
if argocd.IsTemplateAPIAvailable() {
230+
if argocd.CanUseKeycloakWithTemplate() {
231+
setupLog.Info("Keycloak instance can be managed using OpenShift Template")
231232
if err := templatev1.Install(mgr.GetScheme()); err != nil {
232233
setupLog.Error(err, "")
233234
os.Exit(1)
@@ -240,6 +241,8 @@ func main() {
240241
setupLog.Error(err, "")
241242
os.Exit(1)
242243
}
244+
} else {
245+
setupLog.Info("Keycloak instance cannot be managed using OpenShift Template, as DeploymentConfig/Template API is not present")
243246
}
244247

245248
if err = (&argocd.ReconcileArgoCD{

0 commit comments

Comments
 (0)