@@ -18,6 +18,9 @@ package serviceexport
1818
1919import (
2020 "context"
21+ "crypto/sha256"
22+ "encoding/hex"
23+ "sort"
2124
2225 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2326 "k8s.io/apimachinery/pkg/api/errors"
@@ -26,13 +29,12 @@ import (
2629
2730 kubebindv1alpha2 "github.com/kube-bind/kube-bind/sdk/apis/kubebind/v1alpha2"
2831 kubebindhelpers "github.com/kube-bind/kube-bind/sdk/apis/kubebind/v1alpha2/helpers"
29- conditionsapi "github.com/kube-bind/kube-bind/sdk/apis/third_party/conditions/apis/conditions/v1alpha1"
3032 "github.com/kube-bind/kube-bind/sdk/apis/third_party/conditions/util/conditions"
3133)
3234
3335type reconciler struct {
3436 getCRD func (name string ) (* apiextensionsv1.CustomResourceDefinition , error )
35- getAPIResourceSchema func (ctx context.Context , ns , name string ) (* kubebindv1alpha2.APIResourceSchema , error )
37+ getAPIResourceSchema func (ctx context.Context , name string ) (* kubebindv1alpha2.APIResourceSchema , error )
3638 deleteServiceExport func (ctx context.Context , namespace , name string ) error
3739
3840 requeue func (export * kubebindv1alpha2.APIServiceExport )
@@ -44,7 +46,9 @@ func (r *reconciler) reconcile(ctx context.Context, export *kubebindv1alpha2.API
4446 if specChanged , err := r .ensureSchema (ctx , export ); err != nil {
4547 errs = append (errs , err )
4648 } else if specChanged {
47- r .requeue (export )
49+ // TODO: This should be separate controller for apiresourceschemas.
50+ // This is wrong place now.
51+ // r.requeue(export)
4852 return nil
4953 }
5054
@@ -54,56 +58,50 @@ func (r *reconciler) reconcile(ctx context.Context, export *kubebindv1alpha2.API
5458func (r * reconciler ) ensureSchema (ctx context.Context , export * kubebindv1alpha2.APIServiceExport ) (specChanged bool , err error ) {
5559 logger := klog .FromContext (ctx )
5660
61+ var leafHashes []string
5762 for _ , resourceRef := range export .Spec .Resources {
5863 if resourceRef .Type != "APIResourceSchema" {
5964 logger .V (1 ).Info ("Skipping unsupported resource type" , "type" , resourceRef .Type )
6065 continue
6166 }
6267
63- schema , err := r .getAPIResourceSchema (ctx , export . Namespace , resourceRef .Name )
68+ schema , err := r .getAPIResourceSchema (ctx , resourceRef .Name )
6469 if err != nil {
6570 if errors .IsNotFound (err ) {
6671 continue
6772 }
6873 return false , err
6974 }
70- crd , err := r .getCRD (schema .Name )
71- if err != nil && ! errors .IsNotFound (err ) {
72- return false , err
73- }
7475
75- if crd == nil {
76- // CRD missing => delete SER too
77- logger .V (1 ).Info ("Deleting APIServiceExport because CRD is missing" )
78- return false , r .deleteServiceExport (ctx , export .Namespace , export .Name )
79- }
76+ hash := kubebindhelpers .APIResourceSchemaCRDSpecHash (& schema .Spec .APIResourceSchemaCRDSpec )
77+ leafHashes = append (leafHashes , hash )
78+ }
8079
81- expected , err := kubebindhelpers .CRDToAPIResourceSchema (crd , "" )
82- if err != nil {
83- conditions .MarkFalse (
84- export ,
85- kubebindv1alpha2 .APIServiceExportConditionProviderInSync ,
86- "CustomResourceDefinitionUpdateFailed" ,
87- conditionsapi .ConditionSeverityError ,
88- "CustomResourceDefinition %s cannot be converted into a APIServiceExport: %s" ,
89- export .Name , err ,
90- )
91- return false , nil // nothing we can do
92- }
80+ hashOfHashes := hashOfHashes (leafHashes )
9381
94- if hash := kubebindhelpers .APIResourceSchemaCRDSpecHash (& expected .Spec .APIResourceSchemaCRDSpec ); export .Annotations [kubebindv1alpha2 .SourceSpecHashAnnotationKey ] != hash {
95- // both exist, update APIServiceExport
96- logger .V (1 ).Info ("Updating APIServiceExport" )
97- schema .Spec .APIResourceSchemaCRDSpec = expected .Spec .APIResourceSchemaCRDSpec
98- if schema .Annotations == nil {
99- schema .Annotations = map [string ]string {}
100- }
101- schema .Annotations [kubebindv1alpha2 .SourceSpecHashAnnotationKey ] = hash
102- return true , nil
82+ if export .Annotations [kubebindv1alpha2 .SourceSpecHashAnnotationKey ] != hashOfHashes {
83+ // both exist, update APIServiceExport
84+ logger .V (1 ).Info ("Updating APIServiceExport. Hash mismatch" , "hash" , hashOfHashes , "expected" , export .Annotations [kubebindv1alpha2 .SourceSpecHashAnnotationKey ])
85+ if export .Annotations == nil {
86+ export .Annotations = map [string ]string {}
10387 }
104-
105- conditions . MarkTrue ( export , kubebindv1alpha2 . APIServiceExportConditionProviderInSync )
88+ export . Annotations [ kubebindv1alpha2 . SourceSpecHashAnnotationKey ] = hashOfHashes
89+ return true , nil
10690 }
10791
92+ conditions .MarkTrue (export , kubebindv1alpha2 .APIServiceExportConditionProviderInSync )
93+
10894 return false , nil
10995}
96+
97+ func hashOfHashes (hashes []string ) string {
98+ hexHashes := append ([]string {}, hashes ... )
99+
100+ sort .Strings (hexHashes )
101+
102+ rootHasher := sha256 .New ()
103+ for _ , h := range hexHashes {
104+ rootHasher .Write ([]byte (h ))
105+ }
106+ return hex .EncodeToString (rootHasher .Sum (nil ))
107+ }
0 commit comments