Skip to content

Commit 0372ff8

Browse files
Update feature controller to update featureset dependency (#218)
Signed-off-by: Masudur Rahman <[email protected]>
1 parent 2f96f0d commit 0372ff8

File tree

507 files changed

+49810
-20
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

507 files changed

+49810
-20
lines changed

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ require (
3939
k8s.io/kube-state-metrics/v2 v2.7.0
4040
kmodules.xyz/apiversion v0.2.0
4141
kmodules.xyz/authorizer v0.25.1
42-
kmodules.xyz/client-go v0.25.27
42+
kmodules.xyz/client-go v0.25.28
4343
kmodules.xyz/custom-resources v0.25.1
4444
kmodules.xyz/go-containerregistry v0.0.11
4545
kmodules.xyz/monitoring-agent-api v0.25.1
46-
kmodules.xyz/resource-metadata v0.17.9-0.20230725050232-984a47870958
46+
kmodules.xyz/resource-metadata v0.17.9-0.20230727064228-3d5e2c06b6f8
4747
kmodules.xyz/resource-metrics v0.25.2
4848
kmodules.xyz/sets v0.25.0
4949
kubeops.dev/scanner v0.0.13-0.20230610152531-83d060ed8780

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2108,8 +2108,8 @@ kmodules.xyz/apiversion v0.2.0 h1:vAQYqZFm4xu4pbB1cAdHbFEPES6EQkcR4wc06xdTOWk=
21082108
kmodules.xyz/apiversion v0.2.0/go.mod h1:oPX8g8LvlPdPX3Yc5YvCzJHQnw3YF/X4/jdW0b1am80=
21092109
kmodules.xyz/authorizer v0.25.1 h1:W19AtlPD2A1+Q4UqDmNCJKfX9bKIgj+J6bQmkYwsHwY=
21102110
kmodules.xyz/authorizer v0.25.1/go.mod h1:hKAbHpRkbxZJjc+cMTUiyxQxp7amKUVDiN145IrpnhA=
2111-
kmodules.xyz/client-go v0.25.27 h1:Ivl054xbXSvMNMKAJtK7TkS0iZX0AHvVQzxtsrIk9ik=
2112-
kmodules.xyz/client-go v0.25.27/go.mod h1:PYfJtJs+AhgfkJNIeUObU4SqAkY85ARTlXxC+2gAsgo=
2111+
kmodules.xyz/client-go v0.25.28 h1:KmkoiQ6Uf1xqD1Y9owth/OM+0/alOaLdP629Z65HyAk=
2112+
kmodules.xyz/client-go v0.25.28/go.mod h1:SKUDh1za0YOCaqZoNUlg3/pxbWLY8MWLFXx/DiUXv5o=
21132113
kmodules.xyz/crd-schema-fuzz v0.25.0 h1:c5ZxNRqJak1bkGhECmyrKpzKGThFMB4088Kynyvngbc=
21142114
kmodules.xyz/custom-resources v0.25.1 h1:0qHPTxbT/q0afl2GCOnwPFaoxKziRIPXgVu77YwrCa4=
21152115
kmodules.xyz/custom-resources v0.25.1/go.mod h1:ULwzvLmOqZJcPSXKI7iLclYL5eYRlKx8Nbex28Ht19E=
@@ -2119,8 +2119,8 @@ kmodules.xyz/monitoring-agent-api v0.25.1 h1:E1H8U/vMfYQ8wevmJv6Lcj0Z4DF7cH3hZ2x
21192119
kmodules.xyz/monitoring-agent-api v0.25.1/go.mod h1:IphGzRWbuV00B3TLalcBs6+IlchSZVTwKDty+J3LLz4=
21202120
kmodules.xyz/offshoot-api v0.25.0 h1:Svq9da/+sg5afOjpgo9vx2J/Lu90Mo0aFxkdQmgKnGI=
21212121
kmodules.xyz/offshoot-api v0.25.0/go.mod h1:ysEBn7LJuT3+s8ynAQA/OG0BSsJugXa6KGtDLMRjlKo=
2122-
kmodules.xyz/resource-metadata v0.17.9-0.20230725050232-984a47870958 h1:KSgFzmsf0mbdS34By/IoaLuUX+1U9mQokIXwE5Hbk0g=
2123-
kmodules.xyz/resource-metadata v0.17.9-0.20230725050232-984a47870958/go.mod h1:gUy7cQ7QvB/SQ3upgsmS4BVxm5NLbJEXBI7M2CLSymA=
2122+
kmodules.xyz/resource-metadata v0.17.9-0.20230727064228-3d5e2c06b6f8 h1:kI0QLIpBWo0EA77je/kMXu/YFq9oUOXIJ1t9+POK3y0=
2123+
kmodules.xyz/resource-metadata v0.17.9-0.20230727064228-3d5e2c06b6f8/go.mod h1:gUy7cQ7QvB/SQ3upgsmS4BVxm5NLbJEXBI7M2CLSymA=
21242124
kmodules.xyz/resource-metrics v0.25.2 h1:BwCb6qyunvQBa0u8UUkw+wYG5/T4qtNtAKcHjSsk0JU=
21252125
kmodules.xyz/resource-metrics v0.25.2/go.mod h1:ZK/52NLuwMk+Jt0bmUtGQHtSxPLYYpsFILG7SJhYPg0=
21262126
kmodules.xyz/sets v0.25.0 h1:belY/3trp/M/CKc1TEteA40jb2uCIdwKHhjpvrIxG+8=
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
Copyright AppsCode Inc. and Contributors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package feature
18+
19+
import (
20+
"context"
21+
22+
"gomodules.xyz/pointer"
23+
"gomodules.xyz/sets"
24+
"k8s.io/apimachinery/pkg/api/errors"
25+
"k8s.io/apimachinery/pkg/types"
26+
cu "kmodules.xyz/client-go/client"
27+
"kmodules.xyz/resource-metadata/apis/ui/v1alpha1"
28+
"sigs.k8s.io/controller-runtime/pkg/client"
29+
)
30+
31+
func (r *frReconciler) updateAllFeatureSetDependencies(ctx context.Context) error {
32+
enabled := pointer.Bool(r.feature.Status.Managed) && pointer.Bool(r.feature.Status.Enabled)
33+
34+
for _, name := range r.feature.Spec.Requirements.Features {
35+
f := &v1alpha1.Feature{}
36+
if err := r.client.Get(ctx, types.NamespacedName{Name: name}, f); err != nil {
37+
if errors.IsNotFound(err) {
38+
// required feature isn't available yet
39+
continue
40+
}
41+
return err
42+
}
43+
44+
if !pointer.Bool(f.Status.Enabled) || f.Spec.FeatureSet == r.feature.Spec.FeatureSet {
45+
// required feature isn't enabled or belongs to same feature set
46+
continue
47+
}
48+
49+
if err := r.updateFeatureSetDependencyStatus(ctx, f.Spec.FeatureSet, enabled); err != nil {
50+
return err
51+
}
52+
53+
}
54+
return nil
55+
}
56+
57+
func (r *frReconciler) updateFeatureSetDependencyStatus(ctx context.Context, fsName string, enabled bool) error {
58+
fs := &v1alpha1.FeatureSet{}
59+
err := r.client.Get(ctx, types.NamespacedName{Name: fsName}, fs)
60+
if err != nil {
61+
return err
62+
}
63+
64+
if enabled {
65+
fs.Status.Dependents = addFeatureDependents(fs.Status.Dependents, r.feature)
66+
} else {
67+
fs.Status.Dependents = removeFeatureDependents(fs.Status.Dependents, r.feature)
68+
}
69+
70+
_, err = cu.PatchStatus(ctx, r.client, fs, func(obj client.Object) client.Object {
71+
in := obj.(*v1alpha1.FeatureSet)
72+
in.Status.Dependents = fs.Status.Dependents
73+
return in
74+
})
75+
return err
76+
}
77+
78+
func addFeatureDependents(dependents v1alpha1.Dependents, f *v1alpha1.Feature) v1alpha1.Dependents {
79+
for idx := range dependents.FeatureSets {
80+
fs := dependents.FeatureSets[idx]
81+
if fs.Name == f.Spec.FeatureSet {
82+
dependents.FeatureSets[idx].Features = addIfNotExists(fs.Features, f.Name)
83+
return dependents
84+
}
85+
}
86+
87+
dependents.FeatureSets = append(dependents.FeatureSets, v1alpha1.DependentFeatureSet{
88+
Name: f.Spec.FeatureSet,
89+
Features: []string{f.Name},
90+
})
91+
return dependents
92+
}
93+
94+
func removeFeatureDependents(dependents v1alpha1.Dependents, f *v1alpha1.Feature) v1alpha1.Dependents {
95+
dfs := make([]v1alpha1.DependentFeatureSet, 0, len(dependents.FeatureSets))
96+
for idx := range dependents.FeatureSets {
97+
fs := dependents.FeatureSets[idx]
98+
if fs.Name == f.Spec.FeatureSet {
99+
fs.Features = removeIfExists(fs.Features, f.Name)
100+
if len(fs.Features) > 0 {
101+
dfs = append(dfs, fs)
102+
}
103+
} else {
104+
dfs = append(dfs, fs)
105+
}
106+
}
107+
dependents.FeatureSets = dfs
108+
return dependents
109+
}
110+
111+
func addIfNotExists(slice []string, s string) []string {
112+
return sets.NewString(slice...).Insert(s).List()
113+
}
114+
115+
func removeIfExists(slice []string, s string) []string {
116+
return sets.NewString(slice...).Delete(s).List()
117+
}

pkg/controllers/feature/feature_controller.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ func (r *FeatureReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
8989
}
9090

9191
if fr.feature.DeletionTimestamp != nil {
92-
err := fr.updateFeatureSetAndRemoveFinalizer(ctx)
92+
err = fr.updateFeatureSetAndRemoveFinalizer(ctx)
9393
if err != nil && kerr.IsNotFound(err) {
9494
return ctrl.Result{}, err
9595
}
@@ -102,7 +102,7 @@ func (r *FeatureReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
102102
return ctrl.Result{}, nil
103103
}
104104

105-
if err := fr.updateStatus(ctx); err != nil {
105+
if err = fr.updateStatus(ctx); err != nil {
106106
return ctrl.Result{}, err
107107
}
108108

@@ -111,6 +111,10 @@ func (r *FeatureReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
111111
return ctrl.Result{}, err
112112
}
113113

114+
if err = fr.updateAllFeatureSetDependencies(ctx); err != nil {
115+
return ctrl.Result{}, err
116+
}
117+
114118
// We need to requeue the Feature periodically so that it works with third party resources.
115119
// Here, we are requeueing every Feature after a random interval between 30s to 150s so that
116120
// all Features do not get requeued at the same time.

vendor/kmodules.xyz/client-go/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ gen-crd-protos:
154154
--packages=-k8s.io/api/core/v1,kmodules.xyz/client-go/api/v1
155155

156156
.PHONY: gen-enum
157-
gen-enum:
157+
gen-enum: $(BUILD_DIRS)
158158
@docker run \
159159
-i \
160160
--rm \

vendor/kmodules.xyz/client-go/client/client.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,6 @@ func CreateOrPatch(ctx context.Context, c client.Client, obj client.Object, tran
111111
patch = client.MergeFrom(cur)
112112
}
113113
mod := transform(cur.DeepCopyObject().(client.Object), false)
114-
if p, err := patch.Data(mod); err != nil || string(p) == "{}" {
115-
return kutil.VerbUnchanged, err
116-
}
117114
err = c.Patch(ctx, mod, patch, opts...)
118115
if err != nil {
119116
return kutil.VerbUnchanged, err
@@ -149,9 +146,6 @@ func PatchStatus(ctx context.Context, c client.Client, obj client.Object, transf
149146
// - application/apply-patch+yaml
150147
patch := client.MergeFrom(cur)
151148
mod := transform(cur.DeepCopyObject().(client.Object))
152-
if p, err := patch.Data(mod); err != nil || string(p) == "{}" {
153-
return kutil.VerbUnchanged, err
154-
}
155149
err = c.Status().Patch(ctx, mod, patch, opts...)
156150
if err != nil {
157151
return kutil.VerbUnchanged, err
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
Copyright AppsCode Inc. and Contributors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package clientcmd
18+
19+
import (
20+
"k8s.io/apimachinery/pkg/runtime"
21+
"k8s.io/client-go/rest"
22+
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
23+
clientcmdlatest "k8s.io/client-go/tools/clientcmd/api/latest"
24+
)
25+
26+
// https://github.com/kubernetes/client-go/issues/711#issuecomment-730112049
27+
func GenerateKubeConfiguration(cfg *rest.Config, namespace string) ([]byte, error) {
28+
if err := rest.LoadTLSFiles(cfg); err != nil {
29+
return nil, err
30+
}
31+
32+
clusters := make(map[string]*clientcmdapi.Cluster)
33+
clusters["default-cluster"] = &clientcmdapi.Cluster{
34+
Server: cfg.Host,
35+
CertificateAuthorityData: cfg.CAData,
36+
}
37+
38+
contexts := make(map[string]*clientcmdapi.Context)
39+
contexts["default-context"] = &clientcmdapi.Context{
40+
Cluster: "default-cluster",
41+
Namespace: namespace,
42+
AuthInfo: "default-user",
43+
}
44+
45+
authinfos := make(map[string]*clientcmdapi.AuthInfo)
46+
authinfos["default-user"] = &clientcmdapi.AuthInfo{
47+
LocationOfOrigin: "",
48+
ClientCertificate: "",
49+
ClientCertificateData: cfg.CertData,
50+
ClientKey: "",
51+
ClientKeyData: cfg.KeyData,
52+
Token: cfg.BearerToken,
53+
TokenFile: "",
54+
Impersonate: cfg.Impersonate.UserName,
55+
ImpersonateUID: cfg.Impersonate.UID,
56+
ImpersonateGroups: cfg.Impersonate.Groups,
57+
ImpersonateUserExtra: cfg.Impersonate.Extra,
58+
Username: cfg.Username,
59+
Password: cfg.Password,
60+
AuthProvider: cfg.AuthProvider,
61+
Exec: cfg.ExecProvider,
62+
Extensions: nil,
63+
}
64+
65+
clientConfig := clientcmdapi.Config{
66+
Kind: "Config",
67+
APIVersion: "v1",
68+
Clusters: clusters,
69+
Contexts: contexts,
70+
CurrentContext: "default-context",
71+
AuthInfos: authinfos,
72+
}
73+
return runtime.Encode(clientcmdlatest.Codec, &clientConfig)
74+
}

vendor/kmodules.xyz/resource-metadata/apis/meta/v1alpha1/openapi_generated.go

Lines changed: 18 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/kmodules.xyz/resource-metadata/apis/ui/v1alpha1/featureset_types.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ type FeatureSetStatus struct {
7676
// Features specifies the status of the component features that belong to this feature set.
7777
// +optional
7878
Features []ComponentStatus `json:"features,omitempty"`
79+
// Dependents specifies the feature sets which depend on this FeatureSet
80+
// +optional
81+
Dependents Dependents `json:"dependents,omitempty"`
7982
// Note specifies the respective reason if the feature set is considered as disabled.
8083
// +optional
8184
Note string `json:"note,omitempty"`
@@ -95,6 +98,19 @@ type ComponentStatus struct {
9598
Managed *bool `json:"managed,omitempty"`
9699
}
97100

101+
type Dependents struct {
102+
// FeatureSets specifies a list of FeatureSet names that depend on this FeatureSet
103+
// +optional
104+
FeatureSets []DependentFeatureSet `json:"featureSets,omitempty"`
105+
}
106+
107+
type DependentFeatureSet struct {
108+
// Name specifies the name of the dependent FeatureSet
109+
Name string `json:"name,omitempty"`
110+
// Features specifies the Feature names of the dependent FeatureSet
111+
Features []string `json:"features,omitempty"`
112+
}
113+
98114
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
99115
// +kubebuilder:object:root=true
100116

0 commit comments

Comments
 (0)