Make runnable binary

This commit is contained in:
paul 2021-01-10 23:49:22 +01:00
parent 7eedd41bb9
commit b3c1d98534
11 changed files with 368 additions and 23 deletions

View File

@ -21,6 +21,11 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager
# Refer to https://github.com/GoogleContainerTools/distroless for more details
FROM gcr.io/distroless/static:nonroot
WORKDIR /
ENV \
KEYCLOAK_URL=http://keycloak \
KEYCLOAK_USERNAME=keycloak \
KEYCLOAK_PASSWORD= \
KEYCLOAK_REALM=master
COPY --from=builder /workspace/manager .
USER 65532:65532

View File

@ -22,23 +22,36 @@ import (
// KeycloakRealmSpec defines the desired state of KeycloakRealm
type KeycloakRealmSpec struct {
// Name is the name of the Realm
Name string `json:"realmName"`
// RealmName is the name and public identifier of the Realm
RealmName string `json:"realmName"`
// User readable names
DisplayName *string `json:"displayName,omitempty"`
// Secret containing SMTP configuration
SMTPSecretName string `json:"smtpSecretName,omitempty"`
// name shown to the user
DisplayName *string `json:"displayName,omitempty"`
// name including HTML tags, or representing a logo image
DisplayNameHTML *string `json:"displayHTML,omitempty"`
// the name of the Theme used for the login pages
LoginTheme *string `json:"loginTheme,omitempty"`
// Basic realm choices
LoginWithEmailAllowed *bool `json:"loginWithEmailAllowed,omitempty"`
RegistrationAllowed *bool `json:"registrationAllowed,omitempty"`
// if the user can use their email address in the login field
LoginWithEmailAllowed *bool `json:"loginWithEmailAllowed,omitempty"`
// if a user is allowed to self-register via the registration flow
RegistrationAllowed *bool `json:"registrationAllowed,omitempty"`
// if the user should be able to change their username after account creation
EditUsernameAllowed *bool `json:"editUsernameAllowed,omitempty"`
// if the email should be used in place of a selectable user identifier
RegistrationEmailAsUsername *bool `json:"registrationEmailAsUsername,omitempty"`
ResetPasswordAllowed *bool `json:"resetPasswordAllowed,omitempty"`
DuplicateEmailsAllowed *bool `json:"duplicateEmailsAllowed,omitempty"`
VerifyEmail *bool `json:"verifyEmail,omitempty"`
RememberMe *bool `json:"rememberMe,omitempty"`
// if the user is allowed to use the reset password flow
ResetPasswordAllowed *bool `json:"resetPasswordAllowed,omitempty"`
// if emails can be registered multiple times
DuplicateEmailsAllowed *bool `json:"duplicateEmailsAllowed,omitempty"`
// if emails should be verified before the user can log into their account
VerifyEmail *bool `json:"verifyEmail,omitempty"`
// if long-lived sessions should be offered to the user upon login
RememberMe *bool `json:"rememberMe,omitempty"`
}
// KeycloakRealmStatus defines the observed state of KeycloakRealm

View File

@ -111,6 +111,11 @@ func (in *KeycloakRealmSpec) DeepCopyInto(out *KeycloakRealmSpec) {
*out = new(bool)
**out = **in
}
if in.EditUsernameAllowed != nil {
in, out := &in.EditUsernameAllowed, &out.EditUsernameAllowed
*out = new(bool)
**out = **in
}
if in.RegistrationEmailAsUsername != nil {
in, out := &in.RegistrationEmailAsUsername, &out.RegistrationEmailAsUsername
*out = new(bool)

View File

@ -0,0 +1,108 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.1
creationTimestamp: null
name: keycloakrealms.keycloak.bitmask.me
spec:
group: keycloak.bitmask.me
names:
kind: KeycloakRealm
listKind: KeycloakRealmList
plural: keycloakrealms
singular: keycloakrealm
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: KeycloakRealm is the Schema for the keycloakrealms API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: KeycloakRealmSpec defines the desired state of KeycloakRealm
properties:
displayHTML:
description: name including HTML tags, or representing a logo image
type: string
displayName:
description: name shown to the user
type: string
duplicateEmailsAllowed:
description: if emails can be registered multiple times
type: boolean
editUsernameAllowed:
description: if the user should be able to change their username after
account creation
type: boolean
loginTheme:
description: the name of the Theme used for the login pages
type: string
loginWithEmailAllowed:
description: if the user can use their email address in the login
field
type: boolean
realmName:
description: RealmName is the name and public identifier of the Realm
type: string
registrationAllowed:
description: if a user is allowed to self-register via the registration
flow
type: boolean
registrationEmailAsUsername:
description: if the email should be used in place of a selectable
user identifier
type: boolean
rememberMe:
description: if long-lived sessions should be offered to the user
upon login
type: boolean
resetPasswordAllowed:
description: if the user is allowed to use the reset password flow
type: boolean
smtpSecretName:
description: Secret containing SMTP configuration
type: string
verifyEmail:
description: if emails should be verified before the user can log
into their account
type: boolean
required:
- realmName
type: object
status:
description: KeycloakRealmStatus defines the observed state of KeycloakRealm
properties:
available:
type: boolean
id:
type: string
required:
- available
- id
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

34
config/rbac/role.yaml Normal file
View File

@ -0,0 +1,34 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null
name: manager-role
rules:
- apiGroups:
- keycloak.bitmask.me
resources:
- keycloakrealms
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- keycloak.bitmask.me
resources:
- keycloakrealms/finalizers
verbs:
- update
- apiGroups:
- keycloak.bitmask.me
resources:
- keycloakrealms/status
verbs:
- get
- patch
- update

22
controllers/helpers.go Normal file
View File

@ -0,0 +1,22 @@
package controllers
// Helper functions to check and remove string from a slice of strings.
func containsString(slice []string, s string) bool {
for _, item := range slice {
if item == s {
return true
}
}
return false
}
// Helper functions to check and remove string from a slice of strings.
func removeString(slice []string, s string) (result []string) {
for _, item := range slice {
if item == s {
continue
}
result = append(result, item)
}
return
}

View File

@ -0,0 +1,98 @@
package keycloak
import (
"context"
"log"
"sync"
"time"
"github.com/Nerzal/gocloak/v7"
)
// Keycloak contains all information to administrate keycloak
// and stay logged in
type Keycloak struct {
mutex sync.Mutex
client gocloak.GoCloak
accessToken string
validUntil time.Time
user, pass, realm string
}
func (kc *Keycloak) CreateRealmIfNotExists(ctx context.Context, realm gocloak.RealmRepresentation) error {
_, err := kc.client.CreateRealm(ctx, kc.getToken(), realm)
if isConflict(err) {
log.Printf("Realm '%s' already exists, not updated", *realm.Realm)
return nil
}
return err
}
func (kc *Keycloak) CreateProviderIfNotExists(ctx context.Context, realm string, provider gocloak.IdentityProviderRepresentation) error {
_, err := kc.client.CreateIdentityProvider(ctx, kc.getToken(), realm, provider)
if isConflict(err) {
log.Printf("Provider '%s/%s' already exists, not updated", realm, *provider.Alias)
return nil
}
return err
}
func (kc *Keycloak) CreateClientIfNotExists(ctx context.Context, realm string, c gocloak.Client) error {
_, err := kc.client.CreateClient(ctx, kc.getToken(), realm, c)
if isConflict(err) {
log.Printf("Client '%s/%s' already exists, not updated", realm, *c.ClientID)
return nil
}
return err
}
func New(url, user, pass, realm string) (*Keycloak, error) {
kc := &Keycloak{}
kc.client = gocloak.NewClient(url)
kc.user = user
kc.pass = pass
kc.realm = realm
jwt, err := kc.createToken()
kc.accessToken = jwt.AccessToken
kc.validUntil = time.Now().Add(time.Duration(jwt.ExpiresIn) * time.Second)
return kc, err
}
func (kc *Keycloak) getToken() string {
kc.mutex.Lock()
defer kc.mutex.Unlock()
// If token is not valid 30 seconds in the future,
// we need to create a new one
if time.Now().Add(30 * time.Second).After(kc.validUntil) {
jwt, err := kc.createToken()
if err != nil {
log.Fatalf("Valid credentials became invalid: %s", err)
}
kc.accessToken = jwt.AccessToken
kc.validUntil = time.Now().Add(time.Duration(jwt.ExpiresIn) * time.Second)
}
return kc.accessToken
}
func (kc *Keycloak) createToken() (*gocloak.JWT, error) {
token, err := kc.client.LoginAdmin(context.Background(),
kc.user, kc.pass, kc.realm)
if err != nil {
return nil, err
}
return token, nil
}
func isConflict(err error) bool {
if e, ok := err.(*gocloak.APIError); ok {
return (e.Code == 409)
}
return false
}

View File

@ -20,18 +20,26 @@ import (
"context"
"github.com/go-logr/logr"
apierrs "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
keycloakv1alpha1 "git.zom.bi/images/keycloak-operator/api/v1alpha1"
"git.zom.bi/images/keycloak-operator/controllers/keycloak"
)
const (
// FinalizerName is the Name of our finalizer used by this package
FinalizerName = "finalizer.keycloak.bitmask.me"
)
// KeycloakRealmReconciler reconciles a KeycloakRealm object
type KeycloakRealmReconciler struct {
client.Client
Log logr.Logger
Scheme *runtime.Scheme
Keycloak *keycloak.Keycloak
Log logr.Logger
Scheme *runtime.Scheme
}
// +kubebuilder:rbac:groups=keycloak.bitmask.me,resources=keycloakrealms,verbs=get;list;watch;create;update;patch;delete
@ -40,17 +48,37 @@ type KeycloakRealmReconciler struct {
// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
// TODO(user): Modify the Reconcile function to compare the state specified by
// the KeycloakRealm object against the actual cluster state, and then
// perform operations to make the cluster state reflect the state specified by
// the user.
//
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.7.0/pkg/reconcile
func (r *KeycloakRealmReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
_ = r.Log.WithValues("keycloakrealm", req.NamespacedName)
log := r.Log.WithValues("keycloakrealm", req.NamespacedName)
// your logic here
log.Info("reconciling")
var realm keycloakv1alpha1.KeycloakRealm
if err := r.Get(ctx, req.NamespacedName, &realm); err != nil {
if apierrs.IsNotFound(err) {
log.Info("I would now unregister the realm")
return ctrl.Result{}, nil
}
}
if realm.Status.ID != "" {
// try to get existing realm
log.Info("Would try to fetch the realm by its id.",
"id", realm.Status.ID)
// if found {
log.Info("will act like i found it, updating.")
// update()
return ctrl.Result{}, nil
// }
}
log.Info("Would now create the realm.")
realm.Status.ID = "dummy"
realm.Status.Available = true
r.Status().Update(ctx, &realm)
return ctrl.Result{}, nil
}

1
go.mod
View File

@ -3,6 +3,7 @@ module git.zom.bi/images/keycloak-operator
go 1.15
require (
github.com/Nerzal/gocloak/v7 v7.11.0
github.com/go-logr/logr v0.3.0
github.com/onsi/ginkgo v1.14.1
github.com/onsi/gomega v1.10.2

19
go.sum
View File

@ -11,6 +11,7 @@ cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbf
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363/go.mod h1:WG7q7swWsS2f9PYpt5DoEP/EBYWx8We5UoRltn9vJl8=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
@ -34,6 +35,8 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/Nerzal/gocloak/v7 v7.11.0 h1:ab2E55lIMCaUfn47uEHiFhvvMHw+yDHL6Pb+GrM+x04=
github.com/Nerzal/gocloak/v7 v7.11.0/go.mod h1:8fu/dbbIRa1FmLEAOVReZ8PKfbnsl2DwEk6U0giK3KI=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
@ -81,6 +84,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU=
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
@ -158,6 +163,8 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
github.com/go-resty/resty/v2 v2.3.0 h1:JOOeAvjSlapTT92p8xiS19Zxev1neGikoHsXJeOq8So=
github.com/go-resty/resty/v2 v2.3.0/go.mod h1:UpN9CgLZNsv4e9XG50UU8xdI0F43UQ4HmxLBDwaroHU=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
@ -208,6 +215,7 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM=
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
github.com/gordonklaus/ineffassign v0.0.0-20201107091007-3b93a8888063/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
@ -324,6 +332,8 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/segmentio/ksuid v1.0.3 h1:FoResxvleQwYiPAVKe1tMUlEirodZqlqglIuFsdDntY=
github.com/segmentio/ksuid v1.0.3/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@ -352,6 +362,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@ -397,6 +409,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -443,9 +457,12 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -583,6 +600,7 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
@ -595,6 +613,7 @@ gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=

18
main.go
View File

@ -33,6 +33,7 @@ import (
keycloakv1alpha1 "git.zom.bi/images/keycloak-operator/api/v1alpha1"
"git.zom.bi/images/keycloak-operator/controllers"
"git.zom.bi/images/keycloak-operator/controllers/keycloak"
// +kubebuilder:scaffold:imports
)
@ -79,10 +80,21 @@ func main() {
os.Exit(1)
}
kc, err := keycloak.New(
os.Getenv("KEYCLOAK_URL"),
os.Getenv("KEYCLOAK_USERNAME"),
os.Getenv("KEYCLOAK_PASSWORD"),
os.Getenv("KEYCLOAK_REALM"))
if err != nil {
setupLog.Error(err, "unable to connect to keycloak")
os.Exit(1)
}
if err = (&controllers.KeycloakRealmReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("KeycloakRealm"),
Scheme: mgr.GetScheme(),
Client: mgr.GetClient(),
Keycloak: kc,
Log: ctrl.Log.WithName("controllers").WithName("KeycloakRealm"),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "KeycloakRealm")
os.Exit(1)