diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index 308674c..38ca9e8 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -94,11 +94,7 @@ var _ = SynchronizedBeforeSuite(func(ctx SpecContext) []byte { Fail(fmt.Sprintf("failed to add cert-manager.io/v1 to scheme: %v", err)) } - if err := kustomize.ApplyKustomization(ctx, - cl, - scheme, - barmanCloudKustomization, - kustomize.WithIgnoreExistingResources(false)); err != nil { + if err := kustomize.ApplyKustomization(ctx, cl, barmanCloudKustomization); err != nil { Fail(fmt.Sprintf("failed to apply kustomization: %v", err)) } const defaultTimeout = 1 * time.Minute diff --git a/test/e2e/internal/certmanager/certmanager.go b/test/e2e/internal/certmanager/certmanager.go index fff579c..f41aa36 100644 --- a/test/e2e/internal/certmanager/certmanager.go +++ b/test/e2e/internal/certmanager/certmanager.go @@ -21,12 +21,6 @@ import ( "fmt" "time" - admissionregistrationv1 "k8s.io/api/admissionregistration/v1" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - "k8s.io/apimachinery/pkg/runtime" types2 "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/kustomize/api/types" @@ -84,13 +78,7 @@ func Install(ctx context.Context, cl client.Client, opts ...InstallOption) error } // Add all the resources defined in the cert-manager manifests - scheme, err := setupScheme() - if err != nil { - return err - } - - if err := kustomize.ApplyKustomization(ctx, cl, scheme, kustomization, - kustomize.WithIgnoreExistingResources(options.IgnoreExistResources)); err != nil { + if err := kustomize.ApplyKustomization(ctx, cl, kustomization); err != nil { return fmt.Errorf("failed to apply kustomization: %w", err) } @@ -116,24 +104,3 @@ func Install(ctx context.Context, cl client.Client, opts ...InstallOption) error return nil } - -func setupScheme() (*runtime.Scheme, error) { - scheme := runtime.NewScheme() - if err := corev1.AddToScheme(scheme); err != nil { - return nil, fmt.Errorf("failed to add core/v1 to scheme: %w", err) - } - if err := apiextensionsv1.AddToScheme(scheme); err != nil { - return nil, fmt.Errorf("failed to add apiextensions/v1 to scheme: %w", err) - } - if err := admissionregistrationv1.AddToScheme(scheme); err != nil { - return nil, fmt.Errorf("failed to add admissionregistration/v1 to scheme: %w", err) - } - if err := rbacv1.AddToScheme(scheme); err != nil { - return nil, fmt.Errorf("failed to add rbac/v1 to scheme: %w", err) - } - if err := appsv1.AddToScheme(scheme); err != nil { - return nil, fmt.Errorf("failed to add apps/v1 to scheme: %w", err) - } - - return scheme, nil -} diff --git a/test/e2e/internal/cloudnativepg/cloudnativepg.go b/test/e2e/internal/cloudnativepg/cloudnativepg.go index 53c757c..d70b226 100644 --- a/test/e2e/internal/cloudnativepg/cloudnativepg.go +++ b/test/e2e/internal/cloudnativepg/cloudnativepg.go @@ -21,12 +21,6 @@ import ( "fmt" "time" - admissionregistrationv1 "k8s.io/api/admissionregistration/v1" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - "k8s.io/apimachinery/pkg/runtime" types2 "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/kustomize/api/types" @@ -135,13 +129,7 @@ func Install(ctx context.Context, cl client.Client, opts ...InstallOption) error }, } - scheme, err := setupScheme() - if err != nil { - return err - } - - if err := kustomize.ApplyKustomization(ctx, cl, scheme, kustomization, - kustomize.WithIgnoreExistingResources(options.IgnoreExistResources)); err != nil { + if err := kustomize.ApplyKustomization(ctx, cl, kustomization); err != nil { return fmt.Errorf("failed to apply kustomization: %w", err) } @@ -163,23 +151,3 @@ func Install(ctx context.Context, cl client.Client, opts ...InstallOption) error return nil } - -func setupScheme() (*runtime.Scheme, error) { - scheme := runtime.NewScheme() - if err := corev1.AddToScheme(scheme); err != nil { - return nil, fmt.Errorf("failed to add core/v1 to scheme: %w", err) - } - if err := apiextensionsv1.AddToScheme(scheme); err != nil { - return nil, fmt.Errorf("failed to add apiextensions to scheme: %w", err) - } - if err := appsv1.AddToScheme(scheme); err != nil { - return nil, fmt.Errorf("failed to add apps/v1 to scheme: %w", err) - } - if err := rbacv1.AddToScheme(scheme); err != nil { - return nil, fmt.Errorf("failed to add rbac/v1 to scheme: %w", err) - } - if err := admissionregistrationv1.AddToScheme(scheme); err != nil { - return nil, fmt.Errorf("failed to add admissionregistration/v1 to scheme: %w", err) - } - return scheme, nil -} diff --git a/test/e2e/internal/kustomize/kustomize.go b/test/e2e/internal/kustomize/kustomize.go index 81e6f86..4ea6d6f 100644 --- a/test/e2e/internal/kustomize/kustomize.go +++ b/test/e2e/internal/kustomize/kustomize.go @@ -17,16 +17,19 @@ limitations under the License. package kustomize import ( + "bytes" "context" + "errors" "fmt" + "io" + "log" "gopkg.in/yaml.v3" - "k8s.io/apimachinery/pkg/api/errors" + apimachineryerrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/serializer" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/kustomize/api/krusty" + "sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/kyaml/filesys" ) @@ -39,18 +42,10 @@ type ApplyKustomizationOptions struct { // ApplyKustomizationOption is a functional option for ApplyKustomization type ApplyKustomizationOption func(*ApplyKustomizationOptions) -// WithIgnoreExistingResources sets the ignore existing option -func WithIgnoreExistingResources(ignore bool) ApplyKustomizationOption { - return func(opts *ApplyKustomizationOptions) { - opts.IgnoreExistingResources = ignore - } -} - // ApplyKustomization builds the kustomization and creates the resources func ApplyKustomization( ctx context.Context, cl client.Client, - scheme *runtime.Scheme, kustomization *types.Kustomization, options ...ApplyKustomizationOption, ) error { @@ -85,34 +80,60 @@ func ApplyKustomization( return fmt.Errorf("failed to run kustomize: %w", err) } - codecs := serializer.NewCodecFactory(scheme) - deserializer := codecs.UniversalDeserializer() + return applyResourceMap(ctx, cl, resourceMap) +} - // Apply the resources - for _, res := range resourceMap.Resources() { - resJSON, err := res.MarshalJSON() - if err != nil { - return fmt.Errorf("failed to convert resource map to yaml: %w", err) +func applyResourceMap(ctx context.Context, cl client.Client, resourceMap resmap.ResMap) error { + yamlBytes, err := resourceMap.AsYaml() + if err != nil { + return fmt.Errorf("failed to convert resources to YAML: %w", err) + } + r := bytes.NewReader(yamlBytes) + dec := yaml.NewDecoder(r) + for { + // parse the YAML doc + obj := &unstructured.Unstructured{Object: map[string]interface{}{}} + err := dec.Decode(obj.Object) + if errors.Is(err, io.EOF) { + break } - - obj, _, err := deserializer.Decode(resJSON, nil, nil) if err != nil { - return fmt.Errorf("failed to decode resource: %w", err) + return fmt.Errorf("could not decode object: %w", err) } - // TODO: review - unstructuredObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj) - if err != nil { - return fmt.Errorf("failed to convert object to unstructured: %w", err) + if obj.Object == nil { + continue } - u := &unstructured.Unstructured{Object: unstructuredObj} - - if err := cl.Create(ctx, u); err != nil { - if errors.IsAlreadyExists(err) && opts.IgnoreExistingResources { - continue - } - return fmt.Errorf("failed to apply resource: %w", err) + if err := applyResource(ctx, cl, obj); err != nil { + return err } } return nil } + +func applyResource(ctx context.Context, cl client.Client, obj *unstructured.Unstructured) error { + if err := cl.Create(ctx, obj); err != nil { + if apimachineryerrors.IsAlreadyExists(err) { + // If the resource already exists, retrieve the existing resource + existing := &unstructured.Unstructured{} + existing.SetGroupVersionKind(obj.GroupVersionKind()) + key := client.ObjectKey{ + Namespace: obj.GetNamespace(), + Name: obj.GetName(), + } + if err := cl.Get(ctx, key, existing); err != nil { + log.Fatalf("Error getting existing resource: %v", err) + } + + // Update the existing resource with the new data + obj.SetResourceVersion(existing.GetResourceVersion()) + err = cl.Update(ctx, obj) + if err != nil { + return fmt.Errorf("error updating resource: %v", err) + } + } else { + return fmt.Errorf("error creating resource: %v", err) + } + } + return nil +}