Skip to content

Commit

Permalink
fetching data from keycloak works
Browse files Browse the repository at this point in the history
  • Loading branch information
davidgubler committed Aug 29, 2023
1 parent f6dbd5b commit a2c86a5
Show file tree
Hide file tree
Showing 5 changed files with 412 additions and 47 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ There are a bunch of issues this operator needs to overcome. These issues have a

* The Control API has no notion of "admin" users, i.e. users which should have access to everything. The configuration option `CONTROL_API_ADMIN_ORG` allows to specify a Control API organization, and all users who have access to that will be treated as admins.
* The `Organization` and `User` types use different GroupVersions. It seems that this cannot be implemented using a single k8s.io client; instead we need two client instances for the Control API.
* The `OrganizationMember` field `spec.userRefs` contains a lot of invalid values, including even values with incorrect syntax. These must be filtered out.
* The `OrganizationMember` field `spec.userRefs` contains a lot of invalid values, including even values with incorrect syntax. These must be filtered out. Bug report created.
* The value of the `User` field `status.email` is not unique. Since Grafana requires unique email addresses this leads to sync errors. Bug report created.

### Issues with Grafana

Expand Down
88 changes: 45 additions & 43 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,9 @@ package main

import (
"context"
orgs "github.com/appuio/control-api/apis/organization/v1"
controlapi "github.com/appuio/control-api/apis/v1"
controller "github.com/appuio/grafana-organizations-operator/pkg"
grafana "github.com/grafana/grafana-api-golang-client"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/util/json"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"k8s.io/klog/v2"
"net/http"
"net/url"
Expand All @@ -20,13 +15,19 @@ import (
)

var (
ControlApiToken string
ControlApiUrl string
ControlApiAdminOrg string
GrafanaUrl string
GrafanaUsername string
GrafanaPassword string
AdminExtraOrgs = [1]int{1}
ControlApiToken string
ControlApiUrl string
ControlApiAdminOrg string
GrafanaUrl string
GrafanaUsername string
GrafanaPassword string
AdminExtraOrgs = [1]int{1}
KeycloakUrl string
KeycloakRealm string
KeycloakUsername string
KeycloakPassword string
KeycloakClientId string
KeycloakAdminGroupPath string
)

func main() {
Expand All @@ -52,44 +53,45 @@ func main() {
GrafanaPasswordHidden = "***hidden***"
}

klog.Infof("CONTROL_API_URL: %s\n", ControlApiUrl)
klog.Infof("CONTROL_API_ADMIN_ORG: %s\n", ControlApiAdminOrg)
klog.Infof("CONTROL_API_TOKEN: %s\n", ControlApiTokenHidden)
klog.Infof("GRAFANA_URL: %s\n", GrafanaUrl)
klog.Infof("GRAFANA_USERNAME: %s\n", GrafanaUsername)
klog.Infof("GRAFANA_PASSWORD: %s\n", GrafanaPasswordHidden)

// Because of the strange design of the k8s client we actually need two client objects, which both internally use the same httpClient.
// To make this work we also need three (!) config objects, a common one for the httpClient and one for each k8s client.
commonConfig := &rest.Config{}
commonConfig.BearerToken = ControlApiToken
httpClient, err := rest.HTTPClientFor(commonConfig)
if err != nil {
klog.Errorf("Could not create Control API httpClient: %v\n", err)
os.Exit(1)
KeycloakUrl = os.Getenv("KEYCLOAK_URL")
KeycloakRealm = os.Getenv("KEYCLOAK_REALM")
KeycloakUsername = os.Getenv("KEYCLOAK_USERNAME")
KeycloakPassword = os.Getenv("KEYCLOAK_PASSWORD")
KeycloakClientId = os.Getenv("KEYCLOAK_CLIENT_ID")
KeycloakPasswordHidden := ""
if KeycloakPassword != "" {
KeycloakPasswordHidden = "***hidden***"
}
KeycloakAdminGroupPath = os.Getenv("KEYCLOAK_ADMIN_GROUP_PATH")

klog.Infof("CONTROL_API_URL: %s\n", ControlApiUrl)
klog.Infof("CONTROL_API_ADMIN_ORG: %s\n", ControlApiAdminOrg)
klog.Infof("CONTROL_API_TOKEN: %s\n", ControlApiTokenHidden)
klog.Infof("GRAFANA_URL: %s\n", GrafanaUrl)
klog.Infof("GRAFANA_USERNAME: %s\n", GrafanaUsername)
klog.Infof("GRAFANA_PASSWORD: %s\n", GrafanaPasswordHidden)
klog.Infof("KEYCLOAK_URL: %s\n", KeycloakUrl)
klog.Infof("KEYCLOAK_REALM: %s\n", KeycloakRealm)
klog.Infof("KEYCLOAK_USERNAME: %s\n", KeycloakUsername)
klog.Infof("KEYCLOAK_PASSWORD: %s\n", KeycloakPasswordHidden)
klog.Infof("KEYCLOAK_CLIENT_ID: %s\n", KeycloakClientId)
klog.Infof("KEYCLOAK_ADMIN_GROUP_PATH: %s\n", KeycloakAdminGroupPath)

organizationAppuioIoConfig := &rest.Config{}
organizationAppuioIoConfig.Host = ControlApiUrl
organizationAppuioIoConfig.APIPath = "/apis"
organizationAppuioIoConfig.GroupVersion = &orgs.GroupVersion
organizationAppuioIoConfig.NegotiatedSerializer = serializer.NewCodecFactory(scheme.Scheme)
organizationAppuioIoClient, err := rest.RESTClientForConfigAndClient(organizationAppuioIoConfig, httpClient)
keycloak, err := controller.NewKeycloakClient(KeycloakUrl, KeycloakRealm, KeycloakUsername, KeycloakPassword, KeycloakClientId, KeycloakAdminGroupPath)
if err != nil {
klog.Errorf("Could not create Control API client for organization.appuio.io: %v\n", err)
klog.Errorf("Could not create keycloak client: %v\n", err)
os.Exit(1)
}

appuioIoConfig := &rest.Config{}
appuioIoConfig.Host = ControlApiUrl
appuioIoConfig.APIPath = "/apis"
appuioIoConfig.GroupVersion = &controlapi.GroupVersion
appuioIoConfig.NegotiatedSerializer = serializer.NewCodecFactory(scheme.Scheme)
appuioIoClient, err := rest.RESTClientForConfigAndClient(appuioIoConfig, httpClient)
/*keycloakAdmins, err := keycloak.GetAdminUsers(keycloakToken)
if err != nil {
klog.Errorf("Could not connect Control API client for appuio.io: %v\n", err)
klog.Errorf("Could not get keycloak admin users: %v\n", err)
os.Exit(1)
}
fmt.Printf("Admins:\n")
for _, keycloakUser := range keycloakAdmins {
fmt.Printf("%s\n", keycloakUser.Email)
}*/

grafanaConfig := grafana.Config{Client: http.DefaultClient, BasicAuth: url.UserPassword(GrafanaUsername, GrafanaPassword)}

Expand All @@ -115,7 +117,7 @@ func main() {
json.Unmarshal(db, &dashboard)

klog.Info("Starting initial sync...")
err = controller.Reconcile(ctx, organizationAppuioIoClient, appuioIoClient, ControlApiAdminOrg, grafanaConfig, GrafanaUrl, dashboard)
err = controller.Reconcile(ctx, keycloak, ControlApiAdminOrg, grafanaConfig, GrafanaUrl, dashboard)
if err != nil {
klog.Errorf("Could not do initial reconciliation: %v\n", err)
os.Exit(1)
Expand All @@ -127,7 +129,7 @@ func main() {
case <-ctx.Done():
os.Exit(0)
}
err = controller.Reconcile(ctx, organizationAppuioIoClient, appuioIoClient, ControlApiAdminOrg, grafanaConfig, GrafanaUrl, dashboard)
err = controller.Reconcile(ctx, keycloak, ControlApiAdminOrg, grafanaConfig, GrafanaUrl, dashboard)
if err != nil {
klog.Errorf("Could not reconcile (will retry): %v\n", err)
}
Expand Down
Loading

0 comments on commit a2c86a5

Please sign in to comment.