Skip to content

Commit

Permalink
Merge pull request #136 from projectsyn/collect-ocp-and-additional-facts
Browse files Browse the repository at this point in the history
Collect OCP OAuth route and additional facts
  • Loading branch information
bastjan authored Nov 14, 2023
2 parents 9c10d17 + 506f6bf commit bdceddc
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 17 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ require (
k8s.io/apimachinery v0.28.3
k8s.io/client-go v0.28.3
k8s.io/klog v1.0.0
sigs.k8s.io/controller-runtime v0.16.3
)

require (
Expand Down Expand Up @@ -118,7 +119,6 @@ require (
k8s.io/klog/v2 v2.110.1 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/controller-runtime v0.16.3 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SU
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo=
github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
Expand Down Expand Up @@ -273,6 +275,8 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc=
golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
Expand Down
18 changes: 18 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,24 @@ func main() {
app.Flag("operator-namespace", "Namespace in which the ArgoCD operator will be running").Default("syn-argocd-operator").StringVar(&agent.OperatorNamespace)
app.Flag("argo-image", "Image to be used for the Argo CD deployments").Default(images.DefaultArgoCDImage).StringVar(&agent.ArgoCDImage)
app.Flag("redis-image", "Image to be used for the Argo CD Redis deployment").Default(images.DefaultRedisImage).StringVar(&agent.RedisImage)
app.
Flag(
"additional-facts-config-map",
"Additional facts added to the dynamic facts in the cluster object. Keys in the configmap's data field can't override existing keys.").
Default("additional-facts").
StringVar(&agent.AdditionalFactsConfigMap)
app.
Flag(
"ocp-oauth-route-namespace",
"Namespace for the OpenShift OAuth route").
Default("openshift-authentication").
StringVar(&agent.OCPOAuthRouteNamespace)
app.
Flag(
"ocp-oauth-route-name",
"Name of the OpenShift OAuth route").
Default("oauth-openshift").
StringVar(&agent.OCPOAuthRouteName)

kingpin.MustParse(app.Parse(os.Args[1:]))
}
Expand Down
24 changes: 19 additions & 5 deletions pkg/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import (

"github.com/deepmap/oapi-codegen/v2/pkg/securityprovider"
"github.com/projectsyn/lieutenant-api/pkg/api"
"github.com/projectsyn/steward/pkg/argocd"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/klog"

"github.com/projectsyn/steward/pkg/agent/facts"
"github.com/projectsyn/steward/pkg/argocd"
)

// Agent configures the cluster agent
Expand All @@ -31,8 +33,14 @@ type Agent struct {
OperatorNamespace string
ArgoCDImage string
RedisImage string
// The configmap containing additional facts to be added to the dynamic facts
AdditionalFactsConfigMap string

facts factCollector
// Reference to the OpenShift OAuth route to be added to the dynamic facts
OCPOAuthRouteNamespace string
OCPOAuthRouteName string

facts facts.FactCollector
}

// Run starts the cluster agent
Expand All @@ -58,8 +66,14 @@ func (a *Agent) Run(ctx context.Context) error {
return err
}

a.facts = factCollector{
client: client,
a.facts = facts.FactCollector{
Client: client,

OAuthRouteNamespace: a.OCPOAuthRouteNamespace,
OAuthRouteName: a.OCPOAuthRouteName,

AdditionalFactsConfigMapNamespace: a.Namespace,
AdditionalFactsConfigMapName: a.AdditionalFactsConfigMap,
}

ticker := time.NewTicker(1 * time.Minute)
Expand Down Expand Up @@ -91,7 +105,7 @@ func (a *Agent) registerCluster(ctx context.Context, config *rest.Config, apiCli
DeployKey: &publicKey,
},
}
patchCluster.DynamicFacts, err = a.facts.fetchDynamicFacts(ctx)
patchCluster.DynamicFacts, err = a.facts.FetchDynamicFacts(ctx)
if err != nil {
klog.Errorf("Error fetching dynamic facts: %v", err)
}
Expand Down
47 changes: 41 additions & 6 deletions pkg/agent/facts.go → pkg/agent/facts/facts.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package agent
package facts

import (
"context"
Expand All @@ -7,17 +7,33 @@ import (
"unicode"

"github.com/projectsyn/lieutenant-api/pkg/api"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/version"
"k8s.io/client-go/kubernetes"
"k8s.io/klog"
)

type factCollector struct {
client *kubernetes.Clientset
type FactCollector struct {
Client *kubernetes.Clientset

OAuthRouteNamespace string
OAuthRouteName string

AdditionalFactsConfigMapNamespace string
AdditionalFactsConfigMapName string
}

func (col factCollector) fetchDynamicFacts(ctx context.Context) (*api.DynamicClusterFacts, error) {
func (col FactCollector) FetchDynamicFacts(ctx context.Context) (*api.DynamicClusterFacts, error) {
facts := api.DynamicClusterFacts{}

additionalFacts, err := col.fetchAdditionalFacts(ctx)
if err != nil {
klog.Errorf("Error fetching additional facts: %v", err)
}
for k, v := range additionalFacts {
facts[k] = v
}

kubeVersion, err := col.fetchKubernetesVersion(ctx)
if err != nil {
klog.Errorf("Error fetching kubernetes version: %v", err)
Expand All @@ -34,12 +50,20 @@ func (col factCollector) fetchDynamicFacts(ctx context.Context) (*api.DynamicClu
facts["openshiftVersion"] = ocpVersion
}

ocpOAuthRoute, err := col.fetchOpenshiftOAuthRoute(ctx)
if err != nil {
klog.Errorf("Error fetching openshift oauth route: %v", err)
}
if ocpOAuthRoute != "" {
facts["openshiftOAuthRoute"] = ocpOAuthRoute
}

return &facts, nil
}

func (col factCollector) fetchKubernetesVersion(ctx context.Context) (*version.Info, error) {
func (col FactCollector) fetchKubernetesVersion(ctx context.Context) (*version.Info, error) {
// We are not using `col.client.ServerVersion()` to get context support
body, err := col.client.RESTClient().Get().AbsPath("/version").Do(ctx).Raw()
body, err := col.Client.RESTClient().Get().AbsPath("/version").Do(ctx).Raw()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -70,6 +94,17 @@ func processKubernetesVersion(v version.Info) (version.Info, error) {
return v, nil
}

func (col FactCollector) fetchAdditionalFacts(ctx context.Context) (map[string]string, error) {
if col.AdditionalFactsConfigMapName == "" {
return nil, nil
}
cm, err := col.Client.CoreV1().ConfigMaps(col.AdditionalFactsConfigMapNamespace).Get(ctx, col.AdditionalFactsConfigMapName, metav1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("unable to fetch the additional facts config map: %w", err)
}
return cm.Data, nil
}

func trimVersion(v string) string {
res := []rune{}
for _, r := range v {
Expand Down
2 changes: 1 addition & 1 deletion pkg/agent/facts_test.go → pkg/agent/facts/facts_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package agent
package facts

import (
"testing"
Expand Down
34 changes: 31 additions & 3 deletions pkg/agent/factsopenshift.go → pkg/agent/facts/factsopenshift.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package agent
package facts

import (
"context"
"encoding/json"
"fmt"
"path"
"strings"
"time"

Expand All @@ -30,8 +31,14 @@ type OpenshiftVersion struct {
Status OpenshiftVersionStatus
}

func (col factCollector) fetchOpenshiftVersion(ctx context.Context) (*SemanticVersion, error) {
body, err := col.client.RESTClient().Get().AbsPath("/apis/config.openshift.io/v1/clusterversions/version").Do(ctx).Raw()
type OpenshiftRoute struct {
Spec struct {
Host string
}
}

func (col FactCollector) fetchOpenshiftVersion(ctx context.Context) (*SemanticVersion, error) {
body, err := col.Client.RESTClient().Get().AbsPath("/apis/config.openshift.io/v1/clusterversions/version").Do(ctx).Raw()
if err != nil {
if errors.IsNotFound(err) {
// API server doesn't know `clusterversions` or there is no resource, so we are not running on openshift.
Expand All @@ -48,6 +55,27 @@ func (col factCollector) fetchOpenshiftVersion(ctx context.Context) (*SemanticVe
return processOpenshiftVersion(version)
}

func (col FactCollector) fetchOpenshiftOAuthRoute(ctx context.Context) (string, error) {
body, err := col.Client.RESTClient().Get().
AbsPath(
path.Join("/apis/route.openshift.io/v1/namespaces", col.OAuthRouteNamespace, "routes", col.OAuthRouteName),
).Do(ctx).Raw()
if err != nil {
if errors.IsNotFound(err) {
// API server doesn't know `routes` or there is no resource, so we are not running on openshift.
return "", nil
}
return "", fmt.Errorf("unable to fetch the openshift route: %w", err)
}
var route OpenshiftRoute
err = json.Unmarshal(body, &route)
if err != nil {
return "", fmt.Errorf("unable to parse the openshift route: %w", err)
}

return route.Spec.Host, nil
}

type SemanticVersion struct {
Major string
Minor string
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package agent
package facts

import (
"testing"
Expand Down
49 changes: 49 additions & 0 deletions tools/dynamic_fact_collector/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package main

import (
"context"
"encoding/json"
"flag"
"fmt"

"k8s.io/client-go/kubernetes"
"sigs.k8s.io/controller-runtime/pkg/client/config"

"github.com/projectsyn/steward/pkg/agent/facts"
)

func main() {
ns := flag.String("namespace", "syn", "namespace in which steward is running")
additionalFactsConfigMap := flag.String("additional-facts-config-map", "additional-facts", "configmap containing additional facts to be added to the dynamic facts")
ocpOAuthRouteNamespace := flag.String("ocp-oauth-route-namespace", "openshift-authentication", "Namespace for the OpenShift OAuth route")
ocpOAuthRouteName := flag.String("ocp-oauth-route-name", "oauth-openshift", "Name of the OpenShift OAuth route")

flag.Parse()

cfg := config.GetConfigOrDie()

client, err := kubernetes.NewForConfig(cfg)
if err != nil {
panic(err)
}

c := facts.FactCollector{
Client: client,

OAuthRouteNamespace: *ocpOAuthRouteNamespace,
OAuthRouteName: *ocpOAuthRouteName,

AdditionalFactsConfigMapNamespace: *ns,
AdditionalFactsConfigMapName: *additionalFactsConfigMap,
}

fcts, err := c.FetchDynamicFacts(context.Background())
if err != nil {
panic(err)
}
out, err := json.MarshalIndent(fcts, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(out))
}

0 comments on commit bdceddc

Please sign in to comment.