@@ -2,10 +2,17 @@ package service
22
33import (
44 "context"
5+ "fmt"
6+ "sort"
57 "strings"
68
79 "github.com/Masterminds/semver/v3"
10+ console "github.com/pluralsh/console/go/client"
11+ v1 "github.com/pluralsh/deployment-operator/pkg/controller/v1"
12+ "github.com/pluralsh/deployment-operator/pkg/scraper"
13+ "github.com/samber/lo"
814 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15+ "k8s.io/apimachinery/pkg/runtime/schema"
916 "sigs.k8s.io/controller-runtime/pkg/log"
1017
1118 "github.com/pluralsh/deployment-operator/pkg/cache"
@@ -47,8 +54,7 @@ func (s *ServiceReconciler) ScrapeKube(ctx context.Context) {
4754
4855 serviceMesh := cache .ServiceMesh (hasEBPFDaemonSet )
4956 logger .Info ("detected service mesh" , "serviceMesh" , serviceMesh )
50-
51- if err := s .consoleClient .RegisterRuntimeServices (runtimeServices , nil , serviceMesh ); err != nil {
57+ if err := s .consoleClient .RegisterRuntimeServices (runtimeServices , s .GetDeprecatedCustomResources (ctx ), nil , serviceMesh ); err != nil {
5258 logger .Error (err , "failed to register runtime services, this is an ignorable error but could mean your console needs to be upgraded" )
5359 }
5460}
@@ -100,3 +106,112 @@ func addVersion(services map[string]*client.NamespaceVersion, name, vsn string)
100106 services [name ].Version = vsn
101107 }
102108}
109+
110+ func (s * ServiceReconciler ) getVersionedCrd (ctx context.Context ) (map [string ][]v1.NormalizedVersion , error ) {
111+ crdList , err := s .apiExtClient .ApiextensionsV1 ().CustomResourceDefinitions ().List (ctx , metav1.ListOptions {})
112+ if err != nil {
113+ return nil , err
114+ }
115+ crdVersionsMap := make (map [string ][]v1.NormalizedVersion , len (crdList .Items ))
116+ for _ , crd := range crdList .Items {
117+ kind := crd .Spec .Names .Kind
118+ group := crd .Spec .Group
119+ groupKind := fmt .Sprintf ("%s/%s" , group , kind )
120+ var parsedVersions []v1.NormalizedVersion
121+ for _ , v := range crd .Spec .Versions {
122+ parsed , ok := v1 .ParseVersion (v .Name )
123+ if ! ok {
124+ continue
125+ }
126+ // flag enabling/disabling this version from being served via REST APIs
127+ if ! v .Served {
128+ continue
129+ }
130+ parsedVersions = append (parsedVersions , * parsed )
131+ }
132+ sort .Slice (parsedVersions , func (i , j int ) bool {
133+ return v1 .CompareVersions (parsedVersions [i ], parsedVersions [j ])
134+ })
135+ crdVersionsMap [groupKind ] = parsedVersions
136+ }
137+
138+ return crdVersionsMap , nil
139+ }
140+
141+ func (s * ServiceReconciler ) GetDeprecatedCustomResources (ctx context.Context ) []console.DeprecatedCustomResourceAttributes {
142+ logger := log .FromContext (ctx )
143+ crds , err := s .getVersionedCrd (ctx )
144+ if err != nil {
145+ logger .Error (err , "failed to retrieve versioned CRDs" )
146+ return nil
147+ }
148+
149+ var deprecated []console.DeprecatedCustomResourceAttributes
150+ for groupKind , versions := range crds {
151+ gkList := strings .Split (groupKind , "/" )
152+ if len (gkList ) != 2 {
153+ continue
154+ }
155+ group := gkList [0 ]
156+ kind := gkList [1 ]
157+ d := s .getDeprecatedCustomResourceObjects (ctx , versions , group , kind )
158+ deprecated = append (deprecated , d ... )
159+ }
160+ return deprecated
161+ }
162+
163+ func (s * ServiceReconciler ) getDeprecatedCustomResourceObjects (ctx context.Context , versions []v1.NormalizedVersion , group , kind string ) []console.DeprecatedCustomResourceAttributes {
164+ var deprecatedCustomResourceAttributes []console.DeprecatedCustomResourceAttributes
165+ versionPairs := getVersionPairs (versions )
166+ for _ , version := range versionPairs {
167+ gvk := schema.GroupVersionKind {
168+ Group : group ,
169+ Version : version .PreviousVersion ,
170+ Kind : kind ,
171+ }
172+
173+ pager := scraper .ListResources (ctx , s .k8sClient , gvk , nil )
174+ for pager .HasNext () {
175+ items , err := pager .NextPage ()
176+ if err != nil {
177+ break
178+ }
179+ for _ , item := range items {
180+ attr := console.DeprecatedCustomResourceAttributes {
181+ Group : group ,
182+ Kind : kind ,
183+ Name : item .GetName (),
184+ Version : version .PreviousVersion ,
185+ NextVersion : version .LatestVersion ,
186+ }
187+ if item .GetNamespace () != "" {
188+ attr .Namespace = lo .ToPtr (item .GetNamespace ())
189+ }
190+ deprecatedCustomResourceAttributes = append (deprecatedCustomResourceAttributes , attr )
191+ }
192+ }
193+ }
194+ return deprecatedCustomResourceAttributes
195+ }
196+
197+ type VersionPair struct {
198+ LatestVersion string
199+ PreviousVersion string
200+ }
201+
202+ func getVersionPairs (versions []v1.NormalizedVersion ) []VersionPair {
203+ // Helper function for creating VersionPair
204+ createVersionPair := func (latest , previous v1.NormalizedVersion ) VersionPair {
205+ return VersionPair {
206+ LatestVersion : latest .Raw ,
207+ PreviousVersion : previous .Raw ,
208+ }
209+ }
210+
211+ versionPairs := make ([]VersionPair , 0 , len (versions )- 1 ) // Preallocate slice capacity
212+ for i := 0 ; i < len (versions )- 1 ; i ++ {
213+ versionPair := createVersionPair (versions [i ], versions [i + 1 ])
214+ versionPairs = append (versionPairs , versionPair )
215+ }
216+ return versionPairs
217+ }
0 commit comments