From d467ca9ab6f1f1f1125759c70ea6cb2563a9c260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Thu, 9 Apr 2026 14:05:13 +0200 Subject: [PATCH 1/2] Add e2e tests for private Git repository authentication Tests verify that the operator correctly handles private Git repositories using authentication credentials specified via .spec.repository.authSecretRef. --- test/e2e/func_deploy_test.go | 274 +++++++++++++++++++++++++++++++++++ test/utils/gitea.go | 5 +- 2 files changed, 277 insertions(+), 2 deletions(-) diff --git a/test/e2e/func_deploy_test.go b/test/e2e/func_deploy_test.go index 77285e7..38a102a 100644 --- a/test/e2e/func_deploy_test.go +++ b/test/e2e/func_deploy_test.go @@ -27,6 +27,7 @@ import ( "github.com/functions-dev/func-operator/test/utils" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" ) @@ -296,4 +297,277 @@ var _ = Describe("Operator", func() { Eventually(funcBecomeReady, 2*time.Minute).Should(Succeed()) }) }) + Context("with a private repository", func() { + var repoURL string + var repoDir string + var username, password, token string + var functionName, functionNamespace string + + BeforeEach(func() { + // Create repository provider resources with automatic cleanup + var cleanup func() + var err error + + username, password, _, cleanup, err = repoProvider.CreateRandomUser() + Expect(err).NotTo(HaveOccurred()) + DeferCleanup(cleanup) + + _, repoURL, cleanup, err = repoProvider.CreateRandomRepo(username, true) // private repo + Expect(err).NotTo(HaveOccurred()) + DeferCleanup(cleanup) + + // Create access token for the user + token, err = repoProvider.CreateAccessToken(username, password, "e2e-token") + Expect(err).NotTo(HaveOccurred()) + + // Initialize repository with function code + repoDir, err = utils.InitializeRepoWithFunction(repoURL, username, password, "go") + Expect(err).NotTo(HaveOccurred()) + DeferCleanup(os.RemoveAll, repoDir) + + functionNamespace, err = utils.GetTestNamespace() + Expect(err).NotTo(HaveOccurred()) + DeferCleanup(cleanupNamespaces, functionNamespace) + + // Deploy function using func CLI + out, err := utils.RunFunc("deploy", + "--namespace", functionNamespace, + "--path", repoDir, + "--registry", registry, + fmt.Sprintf("--registry-insecure=%t", registryInsecure)) + Expect(err).NotTo(HaveOccurred()) + _, _ = fmt.Fprint(GinkgoWriter, out) + + // Cleanup func deployment + DeferCleanup(func() { + _, _ = utils.RunFunc("delete", "--path", repoDir, "--namespace", functionNamespace) + }) + + // Commit func.yaml changes + err = utils.CommitAndPush(repoDir, "Update func.yaml after deploy", "func.yaml") + Expect(err).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + logFailedTestDetails(functionName, functionNamespace) + + // Cleanup function resource + if functionName != "" { + cmd := exec.Command("kubectl", "delete", "function", functionName, "-n", functionNamespace, "--ignore-not-found") + _, err := utils.Run(cmd) + Expect(err).NotTo(HaveOccurred()) + } + }) + + Context("using token authentication", func() { + It("should mark the function as ready when authSecretRef is provided", func() { + // Create auth secret with token + secret := &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "git-auth-", + Namespace: functionNamespace, + }, + Data: map[string][]byte{ + "token": []byte(token), + }, + } + err := k8sClient.Create(ctx, secret) + Expect(err).NotTo(HaveOccurred()) + DeferCleanup(func() { + _ = k8sClient.Delete(ctx, secret) + }) + + // Create a Function resource with authSecretRef + function := &functionsdevv1alpha1.Function{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "my-private-function-", + Namespace: functionNamespace, + }, + Spec: functionsdevv1alpha1.FunctionSpec{ + Repository: functionsdevv1alpha1.FunctionSpecRepository{ + URL: repoURL, + AuthSecretRef: &v1.LocalObjectReference{ + Name: secret.Name, + }, + }, + }, + } + + err = k8sClient.Create(ctx, function) + Expect(err).NotTo(HaveOccurred()) + + functionName = function.Name + + funcBecomeReady := func(g Gomega) { + fn := &functionsdevv1alpha1.Function{} + err := k8sClient.Get(ctx, types.NamespacedName{Name: function.Name, Namespace: function.Namespace}, fn) + g.Expect(err).NotTo(HaveOccurred()) + + for _, cond := range fn.Status.Conditions { + if cond.Type == functionsdevv1alpha1.TypeReady { + g.Expect(cond.Status).To(Equal(metav1.ConditionTrue)) + return + } + } + g.Expect(false).To(BeTrue(), "Ready condition not found") + } + + Eventually(funcBecomeReady, 6*time.Minute).Should(Succeed()) + }) + + It("should fail with authentication error when authSecretRef is not provided", func() { + // Create a Function resource WITHOUT authSecretRef for private repo + function := &functionsdevv1alpha1.Function{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "my-private-function-noauth-", + Namespace: functionNamespace, + }, + Spec: functionsdevv1alpha1.FunctionSpec{ + Repository: functionsdevv1alpha1.FunctionSpecRepository{ + URL: repoURL, + // No AuthSecretRef + }, + }, + } + + err := k8sClient.Create(ctx, function) + Expect(err).NotTo(HaveOccurred()) + + functionName = function.Name + + funcFailsWithAuthError := func(g Gomega) { + fn := &functionsdevv1alpha1.Function{} + err := k8sClient.Get(ctx, types.NamespacedName{Name: function.Name, Namespace: function.Namespace}, fn) + g.Expect(err).NotTo(HaveOccurred()) + + // Check it's NOT Ready + for _, cond := range fn.Status.Conditions { + if cond.Type == functionsdevv1alpha1.TypeReady { + g.Expect(cond.Status).NotTo(Equal(metav1.ConditionTrue)) + } + // Check for SourceReady condition with auth error + if cond.Type == functionsdevv1alpha1.TypeSourceReady { + g.Expect(cond.Status).To(Equal(metav1.ConditionFalse)) + g.Expect(cond.Message).To(Or( + ContainSubstring("authentication"), + ContainSubstring("Authentication"), + ContainSubstring("401"), + ContainSubstring("Unauthorized"), + )) + return + } + } + g.Expect(false).To(BeTrue(), "SourceReady condition not found") + } + + Eventually(funcFailsWithAuthError, 2*time.Minute).Should(Succeed()) + }) + }) + + Context("using username/password authentication", func() { + It("should mark the function as ready when authSecretRef is provided", func() { + // Create auth secret with username and password + secret := &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "git-auth-", + Namespace: functionNamespace, + }, + Data: map[string][]byte{ + "username": []byte(username), + "password": []byte(password), + }, + } + err := k8sClient.Create(ctx, secret) + Expect(err).NotTo(HaveOccurred()) + DeferCleanup(func() { + _ = k8sClient.Delete(ctx, secret) + }) + + // Create a Function resource with authSecretRef + function := &functionsdevv1alpha1.Function{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "my-private-function-", + Namespace: functionNamespace, + }, + Spec: functionsdevv1alpha1.FunctionSpec{ + Repository: functionsdevv1alpha1.FunctionSpecRepository{ + URL: repoURL, + AuthSecretRef: &v1.LocalObjectReference{ + Name: secret.Name, + }, + }, + }, + } + + err = k8sClient.Create(ctx, function) + Expect(err).NotTo(HaveOccurred()) + + functionName = function.Name + + funcBecomeReady := func(g Gomega) { + fn := &functionsdevv1alpha1.Function{} + err := k8sClient.Get(ctx, types.NamespacedName{Name: function.Name, Namespace: function.Namespace}, fn) + g.Expect(err).NotTo(HaveOccurred()) + + for _, cond := range fn.Status.Conditions { + if cond.Type == functionsdevv1alpha1.TypeReady { + g.Expect(cond.Status).To(Equal(metav1.ConditionTrue)) + return + } + } + g.Expect(false).To(BeTrue(), "Ready condition not found") + } + + Eventually(funcBecomeReady, 6*time.Minute).Should(Succeed()) + }) + + It("should fail with authentication error when authSecretRef is not provided", func() { + // Create a Function resource WITHOUT authSecretRef for private repo + function := &functionsdevv1alpha1.Function{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "my-private-function-noauth-", + Namespace: functionNamespace, + }, + Spec: functionsdevv1alpha1.FunctionSpec{ + Repository: functionsdevv1alpha1.FunctionSpecRepository{ + URL: repoURL, + // No AuthSecretRef + }, + }, + } + + err := k8sClient.Create(ctx, function) + Expect(err).NotTo(HaveOccurred()) + + functionName = function.Name + + funcFailsWithAuthError := func(g Gomega) { + fn := &functionsdevv1alpha1.Function{} + err := k8sClient.Get(ctx, types.NamespacedName{Name: function.Name, Namespace: function.Namespace}, fn) + g.Expect(err).NotTo(HaveOccurred()) + + // Check it's NOT Ready + for _, cond := range fn.Status.Conditions { + if cond.Type == functionsdevv1alpha1.TypeReady { + g.Expect(cond.Status).NotTo(Equal(metav1.ConditionTrue)) + } + // Check for SourceReady condition with auth error + if cond.Type == functionsdevv1alpha1.TypeSourceReady { + g.Expect(cond.Status).To(Equal(metav1.ConditionFalse)) + g.Expect(cond.Message).To(Or( + ContainSubstring("authentication"), + ContainSubstring("Authentication"), + ContainSubstring("401"), + ContainSubstring("Unauthorized"), + )) + return + } + } + g.Expect(false).To(BeTrue(), "SourceReady condition not found") + } + + Eventually(funcFailsWithAuthError, 2*time.Minute).Should(Succeed()) + }) + }) + }) }) diff --git a/test/utils/gitea.go b/test/utils/gitea.go index 32ede3b..797a908 100644 --- a/test/utils/gitea.go +++ b/test/utils/gitea.go @@ -183,9 +183,10 @@ func (g *GiteaClient) CreateAccessToken(username, password, tokenName string) (s return "", fmt.Errorf("failed to create user client: %w", err) } - // Create token + // Create token with all scopes token, _, err := userClient.CreateAccessToken(gitea.CreateAccessTokenOption{ - Name: tokenName, + Name: tokenName, + Scopes: []gitea.AccessTokenScope{gitea.AccessTokenScopeAll}, }) if err != nil { return "", fmt.Errorf("failed to create access token for %s: %w", username, err) From dd91561dfa9216760c365134a245f35765a16169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Thu, 9 Apr 2026 14:56:18 +0200 Subject: [PATCH 2/2] Refactor e2e tests to use shared helper function Extract duplicated funcBecomeReady closures into a reusable functionBecomesReady helper function to reduce code duplication across all e2e test files. --- test/e2e/bundle_test.go | 16 +- test/e2e/func_deploy_test.go | 228 ++++++++++-------------- test/e2e/func_middleware_update_test.go | 33 +--- 3 files changed, 102 insertions(+), 175 deletions(-) diff --git a/test/e2e/bundle_test.go b/test/e2e/bundle_test.go index 8997d4c..840fd0f 100644 --- a/test/e2e/bundle_test.go +++ b/test/e2e/bundle_test.go @@ -311,21 +311,7 @@ func CreateFunctionAndWaitForReady(testNs TestNamespace) { err := k8sClient.Create(ctx, function) Expect(err).NotTo(HaveOccurred()) - funcBecomeReady := func(g Gomega) { - fn := &functionsdevv1alpha1.Function{} - err := k8sClient.Get(ctx, types.NamespacedName{Name: function.Name, Namespace: function.Namespace}, fn) - g.Expect(err).NotTo(HaveOccurred()) - - for _, cond := range fn.Status.Conditions { - if cond.Type == functionsdevv1alpha1.TypeReady { - g.Expect(cond.Status).To(Equal(metav1.ConditionTrue)) - return - } - } - g.Expect(false).To(BeTrue(), "Ready condition not found") - } - - Eventually(funcBecomeReady, 5*time.Minute).Should(Succeed()) + Eventually(functionBecomesReady(function.Name, function.Namespace), 5*time.Minute).Should(Succeed()) } func CreateFunctionAndWaitForConsistentlyNotReconciled(testNs TestNamespace) { diff --git a/test/e2e/func_deploy_test.go b/test/e2e/func_deploy_test.go index 38a102a..542c0e7 100644 --- a/test/e2e/func_deploy_test.go +++ b/test/e2e/func_deploy_test.go @@ -32,6 +32,98 @@ import ( "k8s.io/apimachinery/pkg/types" ) +// expectFunctionConditionTrue returns a Gomega function that checks if a Function +// has the specified condition type with status True +func expectFunctionConditionTrue(functionName, functionNamespace string, conditionType string) func(g Gomega) { + return func(g Gomega) { + fn := &functionsdevv1alpha1.Function{} + err := k8sClient.Get(ctx, types.NamespacedName{Name: functionName, Namespace: functionNamespace}, fn) + g.Expect(err).NotTo(HaveOccurred()) + + for _, cond := range fn.Status.Conditions { + if cond.Type == conditionType { + g.Expect(cond.Status).To(Equal(metav1.ConditionTrue)) + return + } + } + g.Expect(false).To(BeTrue(), conditionType+" condition not found") + } +} + +// expectFunctionConditionFalseWithReason returns a Gomega function that checks if a Function +// has the specified condition type with status False, specific reason, and message substring +func expectFunctionConditionFalseWithReason( + functionName, + functionNamespace, + conditionType, + reason, + messageSubstring string) func(g Gomega) { + return func(g Gomega) { + fn := &functionsdevv1alpha1.Function{} + err := k8sClient.Get(ctx, types.NamespacedName{Name: functionName, Namespace: functionNamespace}, fn) + g.Expect(err).NotTo(HaveOccurred()) + + for _, cond := range fn.Status.Conditions { + if cond.Type == conditionType { + g.Expect(cond.Status).To(Equal(metav1.ConditionFalse)) + g.Expect(cond.Reason).To(Equal(reason)) + g.Expect(cond.Message).To(ContainSubstring(messageSubstring)) + return + } + } + g.Expect(false).To(BeTrue(), conditionType+" condition not found") + } +} + +// functionBecomesReady is a convenience wrapper for checking if a Function becomes Ready +func functionBecomesReady(functionName, functionNamespace string) func(g Gomega) { + return expectFunctionConditionTrue(functionName, functionNamespace, functionsdevv1alpha1.TypeReady) +} + +// functionMiddlewareUpToDate checks if the middleware condition is true +func functionMiddlewareUpToDate(functionName, functionNamespace string) func(g Gomega) { + return expectFunctionConditionTrue(functionName, functionNamespace, functionsdevv1alpha1.TypeMiddlewareUpToDate) +} + +// functionNotReadyWithAuthError returns a Gomega function that checks if a Function +// is NOT Ready and has an auth error in SourceReady condition +func functionNotReadyWithAuthError(functionName, functionNamespace string) func(g Gomega) { + return func(g Gomega) { + fn := &functionsdevv1alpha1.Function{} + err := k8sClient.Get(ctx, types.NamespacedName{Name: functionName, Namespace: functionNamespace}, fn) + g.Expect(err).NotTo(HaveOccurred()) + + for _, cond := range fn.Status.Conditions { + if cond.Type == functionsdevv1alpha1.TypeReady { + g.Expect(cond.Status).NotTo(Equal(metav1.ConditionTrue)) + } + + // Check for SourceReady condition with auth error + if cond.Type == functionsdevv1alpha1.TypeSourceReady { + g.Expect(cond.Status).To(Equal(metav1.ConditionFalse)) + g.Expect(cond.Message).To(Or( + ContainSubstring("authentication"), + ContainSubstring("Authentication"), + ContainSubstring("401"), + ContainSubstring("Unauthorized"), + )) + return + } + } + g.Expect(false).To(BeTrue(), "SourceReady condition not found") + } +} + +// functionNotDeployed check if the function is not ready as the function was not deployed yet +func functionNotDeployed(functionName, functionNamespace string) func(g Gomega) { + return expectFunctionConditionFalseWithReason( + functionName, + functionNamespace, + functionsdevv1alpha1.TypeDeployed, + "NotDeployed", + "Function not deployed yet") +} + var _ = Describe("Operator", func() { SetDefaultEventuallyTimeout(2 * time.Minute) @@ -110,22 +202,8 @@ var _ = Describe("Operator", func() { functionName = function.Name - funcBecomeReady := func(g Gomega) { - fn := &functionsdevv1alpha1.Function{} - err := k8sClient.Get(ctx, types.NamespacedName{Name: function.Name, Namespace: function.Namespace}, fn) - g.Expect(err).NotTo(HaveOccurred()) - - for _, cond := range fn.Status.Conditions { - if cond.Type == functionsdevv1alpha1.TypeReady { - g.Expect(cond.Status).To(Equal(metav1.ConditionTrue)) - return - } - } - g.Expect(false).To(BeTrue(), "Ready condition not found") - } - // redeploy could take a bit longer therefore give a bit more time - Eventually(funcBecomeReady, 6*time.Minute).Should(Succeed()) + Eventually(functionBecomesReady(functionName, functionNamespace), 6*time.Minute).Should(Succeed()) }) }) Context("with a function in a subdirectory in a monorepo", func() { @@ -205,22 +283,8 @@ var _ = Describe("Operator", func() { functionName = function.Name - funcBecomeReady := func(g Gomega) { - fn := &functionsdevv1alpha1.Function{} - err := k8sClient.Get(ctx, types.NamespacedName{Name: function.Name, Namespace: function.Namespace}, fn) - g.Expect(err).NotTo(HaveOccurred()) - - for _, cond := range fn.Status.Conditions { - if cond.Type == functionsdevv1alpha1.TypeReady { - g.Expect(cond.Status).To(Equal(metav1.ConditionTrue)) - return - } - } - g.Expect(false).To(BeTrue(), "Ready condition not found") - } - // redeploy could take a bit longer therefore give a bit more time - Eventually(funcBecomeReady, 6*time.Minute).Should(Succeed()) + Eventually(functionBecomesReady(functionName, functionNamespace), 6*time.Minute).Should(Succeed()) }) }) Context("with a not yet deployed function", func() { @@ -278,23 +342,7 @@ var _ = Describe("Operator", func() { functionName = function.Name - funcBecomeReady := func(g Gomega) { - fn := &functionsdevv1alpha1.Function{} - err := k8sClient.Get(ctx, types.NamespacedName{Name: function.Name, Namespace: function.Namespace}, fn) - g.Expect(err).NotTo(HaveOccurred()) - - for _, cond := range fn.Status.Conditions { - if cond.Type == functionsdevv1alpha1.TypeDeployed { - g.Expect(cond.Status).To(Equal(metav1.ConditionFalse)) - g.Expect(cond.Reason).To(Equal("NotDeployed")) - g.Expect(cond.Message).To(ContainSubstring("Function not deployed yet")) - return - } - } - g.Expect(false).To(BeTrue(), "Deployed condition not found") - } - - Eventually(funcBecomeReady, 2*time.Minute).Should(Succeed()) + Eventually(functionNotDeployed(functionName, functionNamespace), 2*time.Minute).Should(Succeed()) }) }) Context("with a private repository", func() { @@ -398,21 +446,7 @@ var _ = Describe("Operator", func() { functionName = function.Name - funcBecomeReady := func(g Gomega) { - fn := &functionsdevv1alpha1.Function{} - err := k8sClient.Get(ctx, types.NamespacedName{Name: function.Name, Namespace: function.Namespace}, fn) - g.Expect(err).NotTo(HaveOccurred()) - - for _, cond := range fn.Status.Conditions { - if cond.Type == functionsdevv1alpha1.TypeReady { - g.Expect(cond.Status).To(Equal(metav1.ConditionTrue)) - return - } - } - g.Expect(false).To(BeTrue(), "Ready condition not found") - } - - Eventually(funcBecomeReady, 6*time.Minute).Should(Succeed()) + Eventually(functionBecomesReady(functionName, functionNamespace), 6*time.Minute).Should(Succeed()) }) It("should fail with authentication error when authSecretRef is not provided", func() { @@ -435,32 +469,7 @@ var _ = Describe("Operator", func() { functionName = function.Name - funcFailsWithAuthError := func(g Gomega) { - fn := &functionsdevv1alpha1.Function{} - err := k8sClient.Get(ctx, types.NamespacedName{Name: function.Name, Namespace: function.Namespace}, fn) - g.Expect(err).NotTo(HaveOccurred()) - - // Check it's NOT Ready - for _, cond := range fn.Status.Conditions { - if cond.Type == functionsdevv1alpha1.TypeReady { - g.Expect(cond.Status).NotTo(Equal(metav1.ConditionTrue)) - } - // Check for SourceReady condition with auth error - if cond.Type == functionsdevv1alpha1.TypeSourceReady { - g.Expect(cond.Status).To(Equal(metav1.ConditionFalse)) - g.Expect(cond.Message).To(Or( - ContainSubstring("authentication"), - ContainSubstring("Authentication"), - ContainSubstring("401"), - ContainSubstring("Unauthorized"), - )) - return - } - } - g.Expect(false).To(BeTrue(), "SourceReady condition not found") - } - - Eventually(funcFailsWithAuthError, 2*time.Minute).Should(Succeed()) + Eventually(functionNotReadyWithAuthError(functionName, functionNamespace), 2*time.Minute).Should(Succeed()) }) }) @@ -504,21 +513,7 @@ var _ = Describe("Operator", func() { functionName = function.Name - funcBecomeReady := func(g Gomega) { - fn := &functionsdevv1alpha1.Function{} - err := k8sClient.Get(ctx, types.NamespacedName{Name: function.Name, Namespace: function.Namespace}, fn) - g.Expect(err).NotTo(HaveOccurred()) - - for _, cond := range fn.Status.Conditions { - if cond.Type == functionsdevv1alpha1.TypeReady { - g.Expect(cond.Status).To(Equal(metav1.ConditionTrue)) - return - } - } - g.Expect(false).To(BeTrue(), "Ready condition not found") - } - - Eventually(funcBecomeReady, 6*time.Minute).Should(Succeed()) + Eventually(functionBecomesReady(functionName, functionNamespace), 6*time.Minute).Should(Succeed()) }) It("should fail with authentication error when authSecretRef is not provided", func() { @@ -541,32 +536,7 @@ var _ = Describe("Operator", func() { functionName = function.Name - funcFailsWithAuthError := func(g Gomega) { - fn := &functionsdevv1alpha1.Function{} - err := k8sClient.Get(ctx, types.NamespacedName{Name: function.Name, Namespace: function.Namespace}, fn) - g.Expect(err).NotTo(HaveOccurred()) - - // Check it's NOT Ready - for _, cond := range fn.Status.Conditions { - if cond.Type == functionsdevv1alpha1.TypeReady { - g.Expect(cond.Status).NotTo(Equal(metav1.ConditionTrue)) - } - // Check for SourceReady condition with auth error - if cond.Type == functionsdevv1alpha1.TypeSourceReady { - g.Expect(cond.Status).To(Equal(metav1.ConditionFalse)) - g.Expect(cond.Message).To(Or( - ContainSubstring("authentication"), - ContainSubstring("Authentication"), - ContainSubstring("401"), - ContainSubstring("Unauthorized"), - )) - return - } - } - g.Expect(false).To(BeTrue(), "SourceReady condition not found") - } - - Eventually(funcFailsWithAuthError, 2*time.Minute).Should(Succeed()) + Eventually(functionNotReadyWithAuthError(functionName, functionNamespace), 2*time.Minute).Should(Succeed()) }) }) }) diff --git a/test/e2e/func_middleware_update_test.go b/test/e2e/func_middleware_update_test.go index b6ac572..cc2cf18 100644 --- a/test/e2e/func_middleware_update_test.go +++ b/test/e2e/func_middleware_update_test.go @@ -31,7 +31,6 @@ import ( . "github.com/onsi/gomega" "gopkg.in/yaml.v3" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" funcfn "knative.dev/func/pkg/functions" ) @@ -185,22 +184,8 @@ var _ = Describe("Middleware Update", func() { functionName = fn.Name - funcBecomeReady := func(g Gomega) { - f := &functionsdevv1alpha1.Function{} - err := k8sClient.Get(ctx, types.NamespacedName{Name: fn.Name, Namespace: fn.Namespace}, f) - g.Expect(err).NotTo(HaveOccurred()) - - for _, cond := range f.Status.Conditions { - if cond.Type == functionsdevv1alpha1.TypeReady { - g.Expect(cond.Status).To(Equal(metav1.ConditionTrue)) - return - } - } - g.Expect(false).To(BeTrue(), "Ready condition not found") - } - // Middleware update could take a bit longer therefore give more time - Eventually(funcBecomeReady, 6*time.Minute).Should(Succeed()) + Eventually(functionBecomesReady(functionName, functionNamespace), 6*time.Minute).Should(Succeed()) // Verify middleware was actually updated by inspecting the new image out, err = utils.RunFunc("describe", deployedFunctionName, "-n", functionNamespace, "-o", "yaml") @@ -250,21 +235,7 @@ var _ = Describe("Middleware Update", func() { // The operator should have set a middleware version Expect(updatedMiddlewareVersion).NotTo(BeEmpty(), "Operator should have deployed with middleware-version label set") - // Verify MiddlewareUpToDate condition is True - updatedFunction := &functionsdevv1alpha1.Function{} - err = k8sClient.Get(ctx, types.NamespacedName{Name: fn.Name, Namespace: fn.Namespace}, updatedFunction) - Expect(err).NotTo(HaveOccurred()) - - var middlewareUpToDate bool - for _, cond := range updatedFunction.Status.Conditions { - if cond.Type == functionsdevv1alpha1.TypeMiddlewareUpToDate { - middlewareUpToDate = cond.Status == metav1.ConditionTrue - _, _ = fmt.Fprintf(GinkgoWriter, "MiddlewareUpToDate condition: status=%s, reason=%s\n", - cond.Status, cond.Reason) - break - } - } - Expect(middlewareUpToDate).To(BeTrue(), "MiddlewareUpToDate condition should be True") + Eventually(functionMiddlewareUpToDate(functionName, functionNamespace), 2*time.Minute).Should(Succeed()) }) }) })