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

Set disable to true if one of ExclusionGroup feature is enabled #344

Merged
merged 3 commits into from
Nov 12, 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
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ require (
k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f
k8s.io/kube-state-metrics/v2 v2.12.0
k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0
kmodules.xyz/apiversion v0.2.0
kmodules.xyz/authorizer v0.29.1
kmodules.xyz/client-go v0.30.34
kmodules.xyz/client-go v0.30.37
kmodules.xyz/custom-resources v0.30.0
kmodules.xyz/go-containerregistry v0.0.12
kmodules.xyz/monitoring-agent-api v0.30.2
Expand All @@ -57,6 +58,7 @@ require (
kubeops.dev/falco-ui-server v0.0.4
kubeops.dev/scanner v0.0.18
kubepack.dev/lib-helm v0.29.13
open-cluster-management.io/api v0.15.0
sigs.k8s.io/cli-utils v0.37.2
sigs.k8s.io/controller-runtime v0.18.4
sigs.k8s.io/yaml v1.4.0
Expand Down Expand Up @@ -240,7 +242,6 @@ require (
k8s.io/cli-runtime v0.30.1 // indirect
k8s.io/component-helpers v0.29.0 // indirect
k8s.io/kms v0.30.3 // indirect
k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect
kubevault.dev/apimachinery v0.18.3 // indirect
moul.io/http2curl/v2 v2.3.1-0.20221024080105-10c404f653f7 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 // indirect
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -922,8 +922,8 @@ kmodules.xyz/apiversion v0.2.0 h1:vAQYqZFm4xu4pbB1cAdHbFEPES6EQkcR4wc06xdTOWk=
kmodules.xyz/apiversion v0.2.0/go.mod h1:oPX8g8LvlPdPX3Yc5YvCzJHQnw3YF/X4/jdW0b1am80=
kmodules.xyz/authorizer v0.29.1 h1:uByGGoryKbZcfiEAhjcK/Y345I9mygNQP7DVpkMbNQQ=
kmodules.xyz/authorizer v0.29.1/go.mod h1:kZRhclL8twzyt2bQuJQJbpYww2sc+qFr8I5PPoq/sWY=
kmodules.xyz/client-go v0.30.34 h1:AsmdB6/6jK1MxD+4VgibHA1vTbW1U56I+lPAhO2xf+0=
kmodules.xyz/client-go v0.30.34/go.mod h1:CAu+JlA8RVGtj6LQHu0Q1w2mnFUajuti49c7T1AvGdM=
kmodules.xyz/client-go v0.30.37 h1:hj4BMsNDgRVc2aDPB6Y3x5iCylXTZDZeQPJp/oA6lxs=
kmodules.xyz/client-go v0.30.37/go.mod h1:CAu+JlA8RVGtj6LQHu0Q1w2mnFUajuti49c7T1AvGdM=
kmodules.xyz/crd-schema-fuzz v0.29.1 h1:zJTlWYOrT5dsVVHW8HGcnR/vaWfxQfNh11QwTtkYpcs=
kmodules.xyz/crd-schema-fuzz v0.29.1/go.mod h1:n708z9YQqLMP2KNLQVgBcRJw1QpSWLvpNCEi+KJDOYE=
kmodules.xyz/custom-resources v0.30.0 h1:vR3CbseHMLwR4GvtcJJuRuwIV8voKqFqNii27rMcm1o=
Expand Down Expand Up @@ -952,6 +952,8 @@ kubevault.dev/apimachinery v0.18.3 h1:Bq180AGBYnRXXNWbJ6Zg82+8/3M1Y8WYPez32uTry8
kubevault.dev/apimachinery v0.18.3/go.mod h1:b9uUVFx3a3ThDziL2J2O4xQL+muY1/pGavAhDdJC99E=
moul.io/http2curl/v2 v2.3.1-0.20221024080105-10c404f653f7 h1:NykkTlRB+X40z86cLHdEmuoTxhNKhQebLT379b1EumA=
moul.io/http2curl/v2 v2.3.1-0.20221024080105-10c404f653f7/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE=
open-cluster-management.io/api v0.15.0 h1:lRee1KOlGHZb2scTA7ff9E9Fxt2hJc7jpkHnaCbvkOU=
open-cluster-management.io/api v0.15.0/go.mod h1:9erZEWEn4bEqh0nIX2wA7f/s3KCuFycQdBrPrRzi0QM=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 h1:/U5vjBbQn3RChhv7P11uhYvCSm5G2GaIi5AIGBS6r4c=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0/go.mod h1:z7+wmGM2dfIiLRfrC6jb5kV2Mq/sK1ZP303cxzkV5Y4=
Expand Down
15 changes: 12 additions & 3 deletions pkg/apiserver/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
policyinstall "kubeops.dev/ui-server/apis/policy/install"
policyapi "kubeops.dev/ui-server/apis/policy/v1alpha1"
clustermetacontroller "kubeops.dev/ui-server/pkg/controllers/clustermetadata"
clusterclaimcontroller "kubeops.dev/ui-server/pkg/controllers/feature"
projectquotacontroller "kubeops.dev/ui-server/pkg/controllers/projectquota"
"kubeops.dev/ui-server/pkg/graph"
"kubeops.dev/ui-server/pkg/metricshandler"
Expand Down Expand Up @@ -89,7 +90,6 @@ import (
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
restclient "k8s.io/client-go/rest"
"k8s.io/klog/v2"
"k8s.io/klog/v2/klogr"
"kmodules.xyz/authorizer"
kmapi "kmodules.xyz/client-go/api/v1"
cu "kmodules.xyz/client-go/client"
Expand All @@ -107,6 +107,7 @@ import (
uiinstall "kmodules.xyz/resource-metadata/apis/ui/install"
uiapi "kmodules.xyz/resource-metadata/apis/ui/v1alpha1"
identitylib "kmodules.xyz/resource-metadata/pkg/identity"
clusterv1alpha1 "open-cluster-management.io/api/cluster/v1alpha1"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/manager"
Expand Down Expand Up @@ -140,6 +141,7 @@ func init() {
utilruntime.Must(fluxsrc.AddToScheme(Scheme))
utilruntime.Must(monitoringv1.AddToScheme(Scheme))
utilruntime.Must(falco.AddToScheme(Scheme))
utilruntime.Must(clusterv1alpha1.Install(Scheme))

// we need to add the options to empty v1
// TODO fix the server code to avoid this
Expand Down Expand Up @@ -210,8 +212,7 @@ func (c completedConfig) New(ctx context.Context) (*UIServer, error) {
return nil, err
}

// ctrl.SetLogger(...)
log.SetLogger(klogr.New()) // nolint:staticcheck
log.SetLogger(klog.NewKlogr())
setupLog := log.Log.WithName("setup")

cfg := c.ExtraConfig.ClientConfig
Expand Down Expand Up @@ -298,6 +299,14 @@ func (c completedConfig) New(ctx context.Context) (*UIServer, error) {
}
}

if clustermeta.DetectClusterManager(mgr.GetClient()).ManagedByOCMSpoke() {
err = clusterclaimcontroller.NewClusterClaimReconciler(mgr.GetClient()).SetupWithManager(mgr)
if err != nil {
klog.Error(err, "unable to create controller", "controller", "ClusterClaim")
os.Exit(1)
}
}

s := &UIServer{
GenericAPIServer: genericServer,
Manager: mgr,
Expand Down
107 changes: 107 additions & 0 deletions pkg/controllers/feature/clusterclaim_reconciler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
Copyright AppsCode Inc. and Contributors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package feature

import (
"context"
"fmt"
"sort"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
kmapi "kmodules.xyz/client-go/api/v1"
cu "kmodules.xyz/client-go/client"
uiapi "kmodules.xyz/resource-metadata/apis/ui/v1alpha1"
clusterv1alpha1 "open-cluster-management.io/api/cluster/v1alpha1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"sigs.k8s.io/yaml"
)

type ClusterClaimReconciler struct {
kc client.Client
}

var _ reconcile.Reconciler = &ClusterClaimReconciler{}

func NewClusterClaimReconciler(kc client.Client) *ClusterClaimReconciler {
return &ClusterClaimReconciler{
kc: kc,
}
}

func (r *ClusterClaimReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
var err error
var featureList uiapi.FeatureList
if err = r.kc.List(ctx, &featureList); err != nil {
return ctrl.Result{}, err
}

var enabledFeatures, extFeatures, disabledFeatures []string
for _, feature := range featureList.Items {
if feature.Status.Enabled == nil {
return ctrl.Result{}, fmt.Errorf("feature %s is not reconciled yet", feature.Name)
}
if ptr.Deref(feature.Status.Enabled, false) {
enabledFeatures = append(enabledFeatures, feature.Name)
if !ptr.Deref(feature.Status.Managed, false) {
extFeatures = append(extFeatures, feature.Name)
}
}

if feature.Spec.Disabled {
disabledFeatures = append(disabledFeatures, feature.Name)
}
}

sort.Strings(enabledFeatures)
sort.Strings(extFeatures)
sort.Strings(disabledFeatures)

data, err := yaml.Marshal(kmapi.ClusterClaimFeatures{
EnabledFeatures: enabledFeatures,
ExternallyManagedFeatures: extFeatures,
DisabledFeatures: disabledFeatures,
})
if err != nil {
return ctrl.Result{}, err
}

obj := &clusterv1alpha1.ClusterClaim{
TypeMeta: metav1.TypeMeta{},
ObjectMeta: metav1.ObjectMeta{
Name: kmapi.ClusterClaimKeyFeatures,
},
}
_, err = cu.CreateOrPatch(context.TODO(), r.kc, obj, func(o client.Object, createOp bool) client.Object {
in := o.(*clusterv1alpha1.ClusterClaim)
in.Spec.Value = string(data)
return in
})
if err != nil {
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
}

// SetupWithManager sets up the controller with the Manager.
func (r *ClusterClaimReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&uiapi.Feature{}).
Complete(r)
}
49 changes: 49 additions & 0 deletions pkg/controllers/feature/feature_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"
cu "kmodules.xyz/client-go/client"
meta_util "kmodules.xyz/client-go/meta"
uiapi "kmodules.xyz/resource-metadata/apis/ui/v1alpha1"
Expand Down Expand Up @@ -102,6 +103,12 @@ func (r *FeatureReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return ctrl.Result{}, err
}

if fr.feature.Spec.FeatureExclusionGroup != "" {
if err = fr.handleFeatureExclusionGroups(); err != nil {
return ctrl.Result{}, err
}
}

err = fr.updateFeatureSetEntry(ctx)
if err != nil && !apierrors.IsNotFound(err) {
return ctrl.Result{}, err
Expand Down Expand Up @@ -553,3 +560,45 @@ func (r *FeatureReconciler) findFeatureForHelmRelease(ctx context.Context, relea
},
}
}

func (r *frReconciler) handleFeatureExclusionGroups() error {
var err error
exclusionGroupName := r.feature.Spec.FeatureExclusionGroup

var fs uiapi.FeatureSet
err = r.client.Get(context.Background(), types.NamespacedName{Name: r.feature.Spec.FeatureSet}, &fs)
if err != nil {
return err
}

var exclusionGrp bool
for _, f := range fs.Status.Features {
var otherFeature uiapi.Feature
err = r.client.Get(context.Background(), types.NamespacedName{Name: f.Name}, &otherFeature)
if err != nil {
return err
}

if otherFeature.Spec.FeatureExclusionGroup != exclusionGroupName || otherFeature.Name == r.feature.Name {
continue
}

// Mark the exclusion group as active if this feature is enabled
if ptr.Deref(otherFeature.Status.Enabled, false) {
exclusionGrp = true
}
}

// If feature is in an exclusion group and another feature in that group is enabled,
// disable this feature if it’s not already enabled
if exclusionGrp {
r.feature.Spec.Disabled = !ptr.Deref(r.feature.Status.Enabled, false)
} else {
r.feature.Spec.Disabled = false
}

if err := r.client.Update(context.Background(), r.feature); err != nil {
return err
}
return nil
}
19 changes: 0 additions & 19 deletions vendor/k8s.io/klog/v2/klogr/README.md

This file was deleted.

Loading
Loading