From af878a72815de8df68b2cfb045d1ead2cfd5f7a2 Mon Sep 17 00:00:00 2001 From: Adam Harwayne Date: Fri, 1 May 2020 16:51:59 -0700 Subject: [PATCH 1/7] Copy the PubSub PullSubscription and Topic controllers. --- .../intevents/pullsubscription/doc.go | 18 + .../pullsubscription/keda/controller.go | 143 +++ .../pullsubscription/keda/controller_test.go | 84 ++ .../intevents/pullsubscription/keda/doc.go | 18 + .../pullsubscription/keda/pullsubscription.go | 138 +++ .../keda/pullsubscription_test.go | 879 ++++++++++++++++++ .../pullsubscription/keda/resources/names.go | 12 + .../keda/resources/names_test.go | 38 + .../keda/resources/scaled_object.go | 93 ++ .../keda/resources/scaled_object_test.go | 115 +++ .../intevents/pullsubscription/reconciler.go | 415 +++++++++ .../pullsubscription/resources/labels.go | 32 + .../pullsubscription/resources/names.go | 27 + .../resources/receive_adapter.go | 228 +++++ .../resources/receive_adapter_test.go | 489 ++++++++++ .../pullsubscription/static/controller.go | 142 +++ .../static/controller_test.go | 79 ++ .../intevents/pullsubscription/static/doc.go | 18 + .../static/pullsubscription.go | 63 ++ .../static/pullsubscription_test.go | 827 ++++++++++++++++ pkg/reconciler/intevents/topic/controller.go | 116 +++ .../intevents/topic/controller_test.go | 63 ++ pkg/reconciler/intevents/topic/doc.go | 18 + .../intevents/topic/resources/labels.go | 32 + .../intevents/topic/resources/names.go | 33 + .../intevents/topic/resources/publisher.go | 139 +++ .../topic/resources/publisher_test.go | 229 +++++ pkg/reconciler/intevents/topic/topic.go | 284 ++++++ pkg/reconciler/intevents/topic/topic_test.go | 705 ++++++++++++++ 29 files changed, 5477 insertions(+) create mode 100644 pkg/reconciler/intevents/pullsubscription/doc.go create mode 100644 pkg/reconciler/intevents/pullsubscription/keda/controller.go create mode 100644 pkg/reconciler/intevents/pullsubscription/keda/controller_test.go create mode 100644 pkg/reconciler/intevents/pullsubscription/keda/doc.go create mode 100644 pkg/reconciler/intevents/pullsubscription/keda/pullsubscription.go create mode 100644 pkg/reconciler/intevents/pullsubscription/keda/pullsubscription_test.go create mode 100644 pkg/reconciler/intevents/pullsubscription/keda/resources/names.go create mode 100644 pkg/reconciler/intevents/pullsubscription/keda/resources/names_test.go create mode 100644 pkg/reconciler/intevents/pullsubscription/keda/resources/scaled_object.go create mode 100644 pkg/reconciler/intevents/pullsubscription/keda/resources/scaled_object_test.go create mode 100644 pkg/reconciler/intevents/pullsubscription/reconciler.go create mode 100644 pkg/reconciler/intevents/pullsubscription/resources/labels.go create mode 100644 pkg/reconciler/intevents/pullsubscription/resources/names.go create mode 100644 pkg/reconciler/intevents/pullsubscription/resources/receive_adapter.go create mode 100644 pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go create mode 100644 pkg/reconciler/intevents/pullsubscription/static/controller.go create mode 100644 pkg/reconciler/intevents/pullsubscription/static/controller_test.go create mode 100644 pkg/reconciler/intevents/pullsubscription/static/doc.go create mode 100644 pkg/reconciler/intevents/pullsubscription/static/pullsubscription.go create mode 100644 pkg/reconciler/intevents/pullsubscription/static/pullsubscription_test.go create mode 100644 pkg/reconciler/intevents/topic/controller.go create mode 100644 pkg/reconciler/intevents/topic/controller_test.go create mode 100644 pkg/reconciler/intevents/topic/doc.go create mode 100644 pkg/reconciler/intevents/topic/resources/labels.go create mode 100644 pkg/reconciler/intevents/topic/resources/names.go create mode 100644 pkg/reconciler/intevents/topic/resources/publisher.go create mode 100644 pkg/reconciler/intevents/topic/resources/publisher_test.go create mode 100644 pkg/reconciler/intevents/topic/topic.go create mode 100644 pkg/reconciler/intevents/topic/topic_test.go diff --git a/pkg/reconciler/intevents/pullsubscription/doc.go b/pkg/reconciler/intevents/pullsubscription/doc.go new file mode 100644 index 0000000000..d1569586bd --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package pullsubscription implements the Pub/Sub PullSubscription controllers. +package pullsubscription diff --git a/pkg/reconciler/intevents/pullsubscription/keda/controller.go b/pkg/reconciler/intevents/pullsubscription/keda/controller.go new file mode 100644 index 0000000000..6ce54ac748 --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/keda/controller.go @@ -0,0 +1,143 @@ +/* +Copyright 2020 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package keda + +import ( + "context" + + "go.uber.org/zap" + "k8s.io/client-go/discovery" + "k8s.io/client-go/tools/cache" + + duckv1alpha1 "github.com/google/knative-gcp/pkg/apis/duck/v1alpha1" + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + "github.com/google/knative-gcp/pkg/client/injection/ducks/duck/v1alpha1/resource" + pullsubscriptioninformers "github.com/google/knative-gcp/pkg/client/injection/informers/intevents/v1alpha1/pullsubscription" + pullsubscriptionreconciler "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription" + gpubsub "github.com/google/knative-gcp/pkg/gclient/pubsub" + "github.com/google/knative-gcp/pkg/reconciler" + "github.com/google/knative-gcp/pkg/reconciler/identity" + "github.com/google/knative-gcp/pkg/reconciler/identity/iam" + psreconciler "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription" + "github.com/google/knative-gcp/pkg/reconciler/pubsub" + "github.com/kelseyhightower/envconfig" + + eventingduck "knative.dev/eventing/pkg/duck" + deploymentinformer "knative.dev/pkg/client/injection/kube/informers/apps/v1/deployment" + serviceaccountinformers "knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount" + "knative.dev/pkg/configmap" + "knative.dev/pkg/controller" + "knative.dev/pkg/logging" + "knative.dev/pkg/metrics" + pkgreconciler "knative.dev/pkg/reconciler" + "knative.dev/pkg/resolver" + tracingconfig "knative.dev/pkg/tracing/config" +) + +const ( + // reconcilerName is the name of the reconciler + reconcilerName = "KedaPullSubscriptions" + + // controllerAgentName is the string used by this controller to identify + // itself when creating events. + controllerAgentName = "cloud-run-events-pubsub-keda-pullsubscription-controller" + + resourceGroup = "pullsubscriptions.internal.events.cloud.google.com" +) + +type envConfig struct { + // ReceiveAdapter is the receive adapters image. Required. + ReceiveAdapter string `envconfig:"PUBSUB_RA_IMAGE" required:"true"` +} + +// NewController initializes the controller and is called by the generated code +// Registers event handlers to enqueue events +func NewController( + ctx context.Context, + cmw configmap.Watcher, +) *controller.Impl { + return newControllerWithIAMPolicyManager( + ctx, + cmw, + iam.DefaultIAMPolicyManager()) +} + +func newControllerWithIAMPolicyManager( + ctx context.Context, + cmw configmap.Watcher, + ipm iam.IAMPolicyManager, +) *controller.Impl { + deploymentInformer := deploymentinformer.Get(ctx) + pullSubscriptionInformer := pullsubscriptioninformers.Get(ctx) + serviceAccountInformer := serviceaccountinformers.Get(ctx) + + logger := logging.FromContext(ctx).Named(controllerAgentName).Desugar() + + var env envConfig + if err := envconfig.Process("", &env); err != nil { + logger.Fatal("Failed to process env var", zap.Error(err)) + } + + pubsubBase := &pubsub.PubSubBase{ + Base: reconciler.NewBase(ctx, controllerAgentName, cmw), + } + + r := &Reconciler{ + Base: &psreconciler.Base{ + PubSubBase: pubsubBase, + Identity: identity.NewIdentity(ctx, ipm), + DeploymentLister: deploymentInformer.Lister(), + PullSubscriptionLister: pullSubscriptionInformer.Lister(), + ReceiveAdapterImage: env.ReceiveAdapter, + CreateClientFn: gpubsub.NewClient, + ControllerAgentName: controllerAgentName, + ResourceGroup: resourceGroup, + }, + } + + impl := pullsubscriptionreconciler.NewImpl(ctx, r) + + pubsubBase.Logger.Info("Setting up event handlers") + onlyKedaScaler := pkgreconciler.AnnotationFilterFunc(duckv1alpha1.AutoscalingClassAnnotation, duckv1alpha1.KEDA, false) + + pullSubscriptionHandler := cache.FilteringResourceEventHandler{ + FilterFunc: onlyKedaScaler, + Handler: controller.HandleAll(impl.Enqueue), + } + pullSubscriptionInformer.Informer().AddEventHandlerWithResyncPeriod(pullSubscriptionHandler, reconciler.DefaultResyncPeriod) + + deploymentInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ + FilterFunc: onlyKedaScaler, + Handler: controller.HandleAll(impl.EnqueueControllerOf), + }) + + serviceAccountInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ + FilterFunc: controller.FilterGroupVersionKind(v1alpha1.SchemeGroupVersion.WithKind("Pullsubscription")), + Handler: controller.HandleAll(impl.EnqueueControllerOf), + }) + + r.UriResolver = resolver.NewURIResolver(ctx, impl.EnqueueKey) + r.ReconcileDataPlaneFn = r.ReconcileScaledObject + r.scaledObjectTracker = eventingduck.NewListableTracker(ctx, resource.Get, impl.EnqueueKey, controller.GetTrackerLease(ctx)) + r.discoveryFn = discovery.ServerSupportsVersion + + cmw.Watch(logging.ConfigMapName(), r.UpdateFromLoggingConfigMap) + cmw.Watch(metrics.ConfigMapName(), r.UpdateFromMetricsConfigMap) + cmw.Watch(tracingconfig.ConfigName, r.UpdateFromTracingConfigMap) + + return impl +} diff --git a/pkg/reconciler/intevents/pullsubscription/keda/controller_test.go b/pkg/reconciler/intevents/pullsubscription/keda/controller_test.go new file mode 100644 index 0000000000..350732868c --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/keda/controller_test.go @@ -0,0 +1,84 @@ +/* +Copyright 2020 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package keda + +import ( + "os" + "testing" + + iamtesting "github.com/google/knative-gcp/pkg/reconciler/testing" + + "knative.dev/pkg/configmap" + "knative.dev/pkg/logging" + logtesting "knative.dev/pkg/logging/testing" + "knative.dev/pkg/metrics" + _ "knative.dev/pkg/metrics/testing" + . "knative.dev/pkg/reconciler/testing" + "knative.dev/pkg/system" + tracingconfig "knative.dev/pkg/tracing/config" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + _ "github.com/google/knative-gcp/pkg/client/injection/ducks/duck/v1alpha1/resource/fake" + _ "knative.dev/pkg/client/injection/ducks/duck/v1/addressable/fake" + _ "knative.dev/pkg/client/injection/kube/informers/apps/v1/deployment/fake" + _ "knative.dev/pkg/client/injection/kube/informers/batch/v1/job/fake" + _ "knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount/fake" + _ "knative.dev/pkg/injection/clients/dynamicclient/fake" + + // Why is serving needed here? + _ "knative.dev/serving/pkg/client/injection/informers/serving/v1/service/fake" + // Fake injection informers + _ "github.com/google/knative-gcp/pkg/client/injection/informers/intevents/v1alpha1/pullsubscription/fake" +) + +func TestNew(t *testing.T) { + defer logtesting.ClearAll() + ctx, _ := SetupFakeContext(t) + + _ = os.Setenv("PUBSUB_RA_IMAGE", "PUBSUB_RA_IMAGE") + + c := newControllerWithIAMPolicyManager(ctx, configmap.NewStaticWatcher( + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: logging.ConfigMapName(), + Namespace: system.Namespace(), + }, + Data: map[string]string{}, + }, + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: metrics.ConfigMapName(), + Namespace: system.Namespace(), + }, + Data: map[string]string{}, + }, + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: tracingconfig.ConfigName, + Namespace: system.Namespace(), + }, + Data: map[string]string{}, + }, + ), + iamtesting.NoopIAMPolicyManager) + + if c == nil { + t.Fatal("Expected newControllerWithIAMPolicyManager to return a non-nil value") + } +} diff --git a/pkg/reconciler/intevents/pullsubscription/keda/doc.go b/pkg/reconciler/intevents/pullsubscription/keda/doc.go new file mode 100644 index 0000000000..28bb34c79e --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/keda/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2020 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package keda implements the Pub/Sub PullSubscription controller for Keda-based PullSubscriptions. +package keda diff --git a/pkg/reconciler/intevents/pullsubscription/keda/pullsubscription.go b/pkg/reconciler/intevents/pullsubscription/keda/pullsubscription.go new file mode 100644 index 0000000000..4ec9a81906 --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/keda/pullsubscription.go @@ -0,0 +1,138 @@ +/* +Copyright 2020 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package keda + +import ( + "context" + "fmt" + "strings" + + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + pullsubscriptionreconciler "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription" + psreconciler "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription" + "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription/keda/resources" + "go.uber.org/zap" + appsv1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/api/equality" + apierrs "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/discovery" + eventingduck "knative.dev/eventing/pkg/duck" + + "knative.dev/pkg/logging" + "knative.dev/pkg/reconciler" + "knative.dev/pkg/tracker" +) + +type DiscoverFunc func(discovery.DiscoveryInterface, schema.GroupVersion) error + +// Reconciler implements controller.Reconciler for PullSubscription resources. +type Reconciler struct { + *psreconciler.Base + + // scaledObjectTracker is used to notify us that a Keda ScaledObject has changed so that we can reconcile. + scaledObjectTracker eventingduck.ListableTracker + + // discoveryFn is the function used to discover whether Keda is installed or not. Needed for UTs purposes. + discoveryFn DiscoverFunc +} + +// Check that our Reconciler implements Interface. +var _ pullsubscriptionreconciler.Interface = (*Reconciler)(nil) + +func (r *Reconciler) ReconcileKind(ctx context.Context, ps *v1alpha1.PullSubscription) reconciler.Event { + return r.Base.ReconcileKind(ctx, ps) +} + +// TODO upstream to pkg +func (r *Reconciler) ReconcileScaledObject(ctx context.Context, ra *appsv1.Deployment, src *v1alpha1.PullSubscription) error { + // Check whether KEDA is installed, if not, error out. + // Ideally this should be done in the webhook, thus not even allowing the creation of the object. + if err := r.discoveryFn(r.KubeClientSet.Discovery(), resources.KedaSchemeGroupVersion); err != nil { + if strings.Contains(err.Error(), "server does not support API version") { + logging.FromContext(ctx).Desugar().Error("KEDA not installed, failed to check API version", zap.Any("GroupVersion", resources.KedaSchemeGroupVersion)) + return err + } + } + + existing, err := r.Base.GetOrCreateReceiveAdapter(ctx, ra, src) + if err != nil { + return err + } + // Given than the Deployment replicas will be controlled by Keda, we assume + // the replica count from the existing one is the correct one. + ra.Spec.Replicas = existing.Spec.Replicas + if !equality.Semantic.DeepEqual(ra.Spec, existing.Spec) { + existing.Spec = ra.Spec + _, err = r.KubeClientSet.AppsV1().Deployments(src.Namespace).Update(existing) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Error updating Receive Adapter", zap.Error(err)) + return err + } + } + // Now we reconcile the ScaledObject. + gvr, _ := meta.UnsafeGuessKindToResource(resources.ScaledObjectGVK) + scaledObjectResourceInterface := r.DynamicClientSet.Resource(gvr).Namespace(src.Namespace) + if scaledObjectResourceInterface == nil { + return fmt.Errorf("unable to create dynamic client for ScaledObject") + } + + so := resources.MakeScaledObject(ctx, existing, src) + + apiVersion, kind := resources.ScaledObjectGVK.ToAPIVersionAndKind() + ref := tracker.Reference{ + APIVersion: apiVersion, + Kind: kind, + Name: resources.GenerateScaledObjectName(src), + Namespace: src.Namespace, + } + track := r.scaledObjectTracker.TrackInNamespace(src) + + objRef := ref.ObjectReference() + // Track changes in the ScaledObject. + if err = track(objRef); err != nil { + logging.FromContext(ctx).Desugar().Error("Unable to track changes to ScaledObject", zap.Error(err)) + return err + } + + lister, err := r.scaledObjectTracker.ListerFor(objRef) + if err != nil { + logging.FromContext(ctx).Error("Error getting lister for ScaledObject", zap.Any("so", objRef), zap.Error(err)) + return err + } + + _, err = lister.ByNamespace(so.GetNamespace()).Get(so.GetName()) + if err != nil { + if apierrs.IsNotFound(err) { + _, err = scaledObjectResourceInterface.Create(so, metav1.CreateOptions{}) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to create ScaledObject", zap.Any("so", so), zap.Error(err)) + return err + } + } else { + logging.FromContext(ctx).Desugar().Error("Failed to get ScaledObject", zap.Any("so", so), zap.Error(err)) + return err + } + } + return nil +} + +func (r *Reconciler) FinalizeKind(ctx context.Context, ps *v1alpha1.PullSubscription) reconciler.Event { + return r.Base.FinalizeKind(ctx, ps) +} diff --git a/pkg/reconciler/intevents/pullsubscription/keda/pullsubscription_test.go b/pkg/reconciler/intevents/pullsubscription/keda/pullsubscription_test.go new file mode 100644 index 0000000000..d00273a7e6 --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/keda/pullsubscription_test.go @@ -0,0 +1,879 @@ +/* +Copyright 2020 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package keda + +import ( + "context" + "errors" + "fmt" + "strings" + "testing" + + "github.com/google/knative-gcp/pkg/apis/duck/v1alpha1" + v1 "k8s.io/api/apps/v1" + "knative.dev/pkg/apis" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/discovery" + "k8s.io/client-go/kubernetes/scheme" + clientgotesting "k8s.io/client-go/testing" + + "knative.dev/pkg/client/injection/ducks/duck/v1/addressable" + _ "knative.dev/pkg/client/injection/ducks/duck/v1/addressable/fake" + + "knative.dev/pkg/configmap" + "knative.dev/pkg/controller" + logtesting "knative.dev/pkg/logging/testing" + . "knative.dev/pkg/reconciler/testing" + "knative.dev/pkg/resolver" + + pubsubv1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + "github.com/google/knative-gcp/pkg/client/injection/ducks/duck/v1alpha1/resource" + "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription" + gpubsub "github.com/google/knative-gcp/pkg/gclient/pubsub/testing" + "github.com/google/knative-gcp/pkg/reconciler" + psreconciler "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription" + . "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription/keda/resources" + "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription/resources" + "github.com/google/knative-gcp/pkg/reconciler/pubsub" + . "github.com/google/knative-gcp/pkg/reconciler/testing" + "knative.dev/eventing/pkg/duck" +) + +const ( + sourceName = "source" + sinkName = "sink" + transformerName = "transformer" + + testNS = "testnamespace" + + testImage = "test_image" + + sourceUID = sourceName + "-abc-123" + + testProject = "test-project-id" + testTopicID = sourceUID + "-TOPIC" + testSubscriptionID = "cre-pull-" + sourceUID + generation = 1 + + secretName = "testing-secret" + + failedToReconcileSubscriptionMsg = `Failed to reconcile Pub/Sub subscription` + failedToDeleteSubscriptionMsg = `Failed to delete Pub/Sub subscription` +) + +var ( + sinkDNS = sinkName + ".mynamespace.svc.cluster.local" + sinkURI = apis.HTTP(sinkDNS) + + transformerDNS = transformerName + ".mynamespace.svc.cluster.local" + transformerURI = apis.HTTP(transformerDNS) + + sinkGVK = metav1.GroupVersionKind{ + Group: "testing.cloud.google.com", + Version: "v1alpha1", + Kind: "Sink", + } + + transformerGVK = metav1.GroupVersionKind{ + Group: "testing.cloud.google.com", + Version: "v1alpha1", + Kind: "Transformer", + } + + secret = corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: secretName, + }, + Key: "testing-key", + } +) + +func init() { + // Add types to scheme + _ = pubsubv1alpha1.AddToScheme(scheme.Scheme) +} + +func newSecret() *corev1.Secret { + return &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: testNS, + Name: secretName, + }, + Data: map[string][]byte{ + "testing-key": []byte("abcd"), + }, + } +} + +func newPullSubscription(subscriptionId string) *pubsubv1alpha1.PullSubscription { + return NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Topic: testTopicID, + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + }), + WithPullSubscriptionSubscriptionID(subscriptionId), + WithInitPullSubscriptionConditions, + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + ) +} + +func newSink() *unstructured.Unstructured { + return &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "testing.cloud.google.com/v1alpha1", + "kind": "Sink", + "metadata": map[string]interface{}{ + "namespace": testNS, + "name": sinkName, + }, + "status": map[string]interface{}{ + "address": map[string]interface{}{ + "url": sinkURI.String(), + }, + }, + }, + } +} + +func newAnnotations() map[string]string { + return map[string]string{ + v1alpha1.AutoscalingClassAnnotation: v1alpha1.KEDA, + v1alpha1.AutoscalingMinScaleAnnotation: "0", + v1alpha1.AutoscalingMaxScaleAnnotation: "3", + v1alpha1.KedaAutoscalingSubscriptionSizeAnnotation: "5", + v1alpha1.KedaAutoscalingCooldownPeriodAnnotation: "60", + v1alpha1.KedaAutoscalingPollingIntervalAnnotation: "30", + } +} + +func newTransformer() *unstructured.Unstructured { + return &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "testing.cloud.google.com/v1alpha1", + "kind": "Transformer", + "metadata": map[string]interface{}{ + "namespace": testNS, + "name": transformerName, + }, + "status": map[string]interface{}{ + "address": map[string]interface{}{ + "url": transformerURI.String(), + }, + }, + }, + } +} + +func TestAllCases(t *testing.T) { + table := TableTest{{ + Name: "bad workqueue key", + // Make sure Reconcile handles bad keys. + Key: "too/many/parts", + }, { + Name: "key not found", + // Make sure Reconcile handles good keys that don't exist. + Key: "foo/not-found", + }, { + Name: "cannot get sink", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithPullSubscriptionSink(sinkGVK, sinkName), + ), + newSecret(), + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeWarning, "InvalidSink", + `InvalidSink: failed to get ref &ObjectReference{Kind:Sink,Namespace:testnamespace,Name:sink,UID:,APIVersion:testing.cloud.google.com/v1alpha1,ResourceVersion:,FieldPath:,}: sinks.testing.cloud.google.com "sink" not found`), + }, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithPullSubscriptionSink(sinkGVK, sinkName), + // Updates + WithPullSubscriptionStatusObservedGeneration(generation), + WithInitPullSubscriptionConditions, + WithPullSubscriptionSinkNotFound(), + ), + }}, + }, { + Name: "create client fails", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeWarning, "SubscriptionReconcileFailed", "Failed to reconcile Pub/Sub subscription: client-create-induced-error"), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + CreateClientErr: errors.New("client-create-induced-error"), + }, + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionStatusObservedGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPullSubscriptionTransformerURI(nil), + WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "client-create-induced-error"))), + }}, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + }, { + Name: "topic exists fails", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeWarning, "SubscriptionReconcileFailed", "Failed to reconcile Pub/Sub subscription: topic-exists-induced-error"), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + ExistsErr: errors.New("topic-exists-induced-error"), + }, + }, + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionStatusObservedGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPullSubscriptionTransformerURI(nil), + WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "topic-exists-induced-error"))), + }}, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + }, { + Name: "topic does not exist", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeWarning, "SubscriptionReconcileFailed", "Failed to reconcile Pub/Sub subscription: Topic %q does not exist", testTopicID), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + Exists: false, + }, + }, + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionStatusObservedGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPullSubscriptionTransformerURI(nil), + WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: Topic %q does not exist", failedToReconcileSubscriptionMsg, testTopicID))), + }}, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + }, { + Name: "subscription exists fails", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeWarning, "SubscriptionReconcileFailed", "Failed to reconcile Pub/Sub subscription: subscription-exists-induced-error"), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + SubscriptionData: gpubsub.TestSubscriptionData{ + ExistsErr: errors.New("subscription-exists-induced-error"), + }, + }, + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionStatusObservedGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPullSubscriptionTransformerURI(nil), + WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "subscription-exists-induced-error"))), + }}, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + }, { + Name: "create subscription fails", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeWarning, "SubscriptionReconcileFailed", "Failed to reconcile Pub/Sub subscription: subscription-create-induced-error"), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + Exists: true, + }, + CreateSubscriptionErr: errors.New("subscription-create-induced-error"), + }, + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionStatusObservedGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPullSubscriptionTransformerURI(nil), + WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "subscription-create-induced-error"))), + }}, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + }, { + Name: "successfully created subscription", + Objects: []runtime.Object{ + newPullSubscription(""), + newSink(), + newSecret(), + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeNormal, "PullSubscriptionReconciled", `PullSubscription reconciled: "%s/%s"`, testNS, sourceName), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + Exists: true, + }, + }, + }, + WantCreates: []runtime.Object{ + newScaledObject(newPullSubscription(testSubscriptionID)), + newReceiveAdapter(context.Background(), testImage, nil), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPullSubscriptionTransformerURI(nil), + // Updates + WithPullSubscriptionStatusObservedGeneration(generation), + WithPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPullSubscriptionMarkDeployed, + ), + }}, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + }, { + Name: "successful create - reuse existing receive adapter - match", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithPullSubscriptionSink(sinkGVK, sinkName), + ), + newSink(), + newSecret(), + newReceiveAdapter(context.Background(), testImage, nil), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + Exists: true, + }, + }, + }, + WantCreates: []runtime.Object{ + newScaledObject(newPullSubscription(testSubscriptionID)), + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeNormal, "PullSubscriptionReconciled", `PullSubscription reconciled: "%s/%s"`, testNS, sourceName), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPullSubscriptionMarkDeployed, + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPullSubscriptionTransformerURI(nil), + WithPullSubscriptionStatusObservedGeneration(generation), + ), + }}, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + }, { + Name: "successful create - reuse existing receive adapter - mismatch", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionTransformer(transformerGVK, transformerName), + ), + newSink(), + newTransformer(), + newSecret(), + newReceiveAdapter(context.Background(), "old"+testImage, nil), + }, + WantCreates: []runtime.Object{ + newScaledObject(newPullSubscription(testSubscriptionID)), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + Exists: true, + }, + }, + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeNormal, "PullSubscriptionReconciled", `PullSubscription reconciled: "%s/%s"`, testNS, sourceName), + }, + WantUpdates: []clientgotesting.UpdateActionImpl{{ + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Verb: "update", + Resource: receiveAdapterGVR(), + }, + Object: newReceiveAdapter(context.Background(), testImage, transformerURI), + }}, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionTransformer(transformerGVK, transformerName), + WithPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPullSubscriptionMarkDeployed, + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkTransformer(transformerURI), + WithPullSubscriptionStatusObservedGeneration(generation), + ), + }}, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + }, { + Name: "deleting - failed to delete subscription", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPullSubscriptionMarkDeployed, + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionDeleted, + ), + newSecret(), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + Exists: true, + }, + SubscriptionData: gpubsub.TestSubscriptionData{ + Exists: true, + DeleteErr: errors.New("subscription-delete-induced-error"), + }, + }, + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeWarning, "SubscriptionDeleteFailed", "Failed to delete Pub/Sub subscription: subscription-delete-induced-error"), + }, + WantStatusUpdates: nil, + }, { + Name: "successfully deleted subscription", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPullSubscriptionMarkDeployed, + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionSubscriptionID(""), + WithPullSubscriptionDeleted, + ), + newSecret(), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + Exists: true, + }, + SubscriptionData: gpubsub.TestSubscriptionData{ + Exists: true, + }, + }, + }, + Key: testNS + "/" + sourceName, + WantEvents: nil, + WantStatusUpdates: nil, + }} + + defer logtesting.ClearAll() + table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher, testData map[string]interface{}) controller.Reconciler { + ctx = addressable.WithDuck(ctx) + ctx = resource.WithDuck(ctx) + pubsubBase := &pubsub.PubSubBase{ + Base: reconciler.NewBase(ctx, controllerAgentName, cmw), + } + r := &Reconciler{ + Base: &psreconciler.Base{ + PubSubBase: pubsubBase, + DeploymentLister: listers.GetDeploymentLister(), + PullSubscriptionLister: listers.GetPullSubscriptionLister(), + UriResolver: resolver.NewURIResolver(ctx, func(types.NamespacedName) {}), + ReceiveAdapterImage: testImage, + CreateClientFn: gpubsub.TestClientCreator(testData["ps"]), + ControllerAgentName: controllerAgentName, + ResourceGroup: resourceGroup, + }, + } + r.ReconcileDataPlaneFn = r.ReconcileScaledObject + r.scaledObjectTracker = duck.NewListableTracker(ctx, resource.Get, func(types.NamespacedName) {}, 0) + r.discoveryFn = mockDiscoveryFunc + return pullsubscription.NewReconciler(ctx, r.Logger, r.RunClientSet, listers.GetPullSubscriptionLister(), r.Recorder, r) + })) +} + +func mockDiscoveryFunc(_ discovery.DiscoveryInterface, _ schema.GroupVersion) error { + return nil +} + +func newReceiveAdapter(ctx context.Context, image string, transformer *apis.URL) runtime.Object { + source := NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionAnnotations(map[string]string{ + v1alpha1.AutoscalingClassAnnotation: v1alpha1.KEDA, + v1alpha1.AutoscalingMinScaleAnnotation: "0", + v1alpha1.AutoscalingMaxScaleAnnotation: "3", + v1alpha1.KedaAutoscalingSubscriptionSizeAnnotation: "5", + v1alpha1.KedaAutoscalingCooldownPeriodAnnotation: "60", + v1alpha1.KedaAutoscalingPollingIntervalAnnotation: "30", + }), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + })) + args := &resources.ReceiveAdapterArgs{ + Image: image, + Source: source, + Labels: resources.GetLabels(controllerAgentName, sourceName), + SubscriptionID: testSubscriptionID, + SinkURI: sinkURI, + TransformerURI: transformer, + } + return resources.MakeReceiveAdapter(ctx, args) +} + +func newScaledObject(ps *pubsubv1alpha1.PullSubscription) runtime.Object { + ctx := context.Background() + ra := newReceiveAdapter(ctx, testImage, nil) + d, _ := ra.(*v1.Deployment) + u := MakeScaledObject(ctx, d, ps) + return u +} + +func receiveAdapterGVR() schema.GroupVersionResource { + return schema.GroupVersionResource{ + Group: "apps", + Version: "v1", + Resource: "deployment", + } +} + +func patchFinalizers(namespace, name, finalizer string, existingFinalizers ...string) clientgotesting.PatchActionImpl { + action := clientgotesting.PatchActionImpl{} + action.Name = name + action.Namespace = namespace + + for i, ef := range existingFinalizers { + existingFinalizers[i] = fmt.Sprintf("%q", ef) + } + if finalizer != "" { + existingFinalizers = append(existingFinalizers, fmt.Sprintf("%q", finalizer)) + } + fname := strings.Join(existingFinalizers, ",") + patch := `{"metadata":{"finalizers":[` + fname + `],"resourceVersion":""}}` + action.Patch = []byte(patch) + return action +} diff --git a/pkg/reconciler/intevents/pullsubscription/keda/resources/names.go b/pkg/reconciler/intevents/pullsubscription/keda/resources/names.go new file mode 100644 index 0000000000..0842f89564 --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/keda/resources/names.go @@ -0,0 +1,12 @@ +package resources + +import ( + "fmt" + + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" +) + +// GenerateScaledObjectName generates the name for the ScaledObject based on the PullSubscription UID. +func GenerateScaledObjectName(ps *v1alpha1.PullSubscription) string { + return fmt.Sprintf("cre-so-%s", string(ps.UID)) +} diff --git a/pkg/reconciler/intevents/pullsubscription/keda/resources/names_test.go b/pkg/reconciler/intevents/pullsubscription/keda/resources/names_test.go new file mode 100644 index 0000000000..0e61a3f0f2 --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/keda/resources/names_test.go @@ -0,0 +1,38 @@ +/* +Copyright 2020 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestGenerateScaledObjectName(t *testing.T) { + want := "cre-so-a-uid" + got := GenerateScaledObjectName(&v1alpha1.PullSubscription{ + ObjectMeta: v1.ObjectMeta{ + UID: "a-uid", + }, + }) + + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("unexpected (-want, +got) = %v", diff) + } +} diff --git a/pkg/reconciler/intevents/pullsubscription/keda/resources/scaled_object.go b/pkg/reconciler/intevents/pullsubscription/keda/resources/scaled_object.go new file mode 100644 index 0000000000..c6fde340a6 --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/keda/resources/scaled_object.go @@ -0,0 +1,93 @@ +/* +Copyright 2020 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + "context" + "strconv" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + + duckv1alpha1 "github.com/google/knative-gcp/pkg/apis/duck/v1alpha1" + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + v1 "k8s.io/api/apps/v1" +) + +var ( + ScaledObjectGVK = schema.GroupVersionKind{ + Group: "keda.k8s.io", + Version: "v1alpha1", + Kind: "ScaledObject", + } + + KedaSchemeGroupVersion = schema.GroupVersion{Group: "keda.k8s.io", Version: "v1alpha1"} +) + +func MakeScaledObject(ctx context.Context, ra *v1.Deployment, ps *v1alpha1.PullSubscription) *unstructured.Unstructured { + // These values should have already been validated in the webhook, and be valid ints. Not checking for errors. + minReplicaCount, _ := strconv.ParseInt(ps.Annotations[duckv1alpha1.AutoscalingMinScaleAnnotation], 10, 64) + maxReplicateCount, _ := strconv.ParseInt(ps.Annotations[duckv1alpha1.AutoscalingMaxScaleAnnotation], 10, 64) + cooldownPeriod, _ := strconv.ParseInt(ps.Annotations[duckv1alpha1.KedaAutoscalingCooldownPeriodAnnotation], 10, 64) + pollingInterval, _ := strconv.ParseInt(ps.Annotations[duckv1alpha1.KedaAutoscalingPollingIntervalAnnotation], 10, 64) + + // Using Unstructured instead of adding the Keda dependency. Given that the only way to interact with the scaledObject + // is using the dynamicClient (see https://keda.sh/faq/), it does not make much sense for now to add an extra dependency, + // which BTW brings things like controller-runtime, etc. + so := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "keda.k8s.io/v1alpha1", + "kind": "ScaledObject", + "metadata": map[string]interface{}{ + "namespace": ra.Namespace, + "name": GenerateScaledObjectName(ps), + "labels": map[string]interface{}{ + "deploymentName": ra.Name, + "events.cloud.google.com/ps-name": ps.Name, + }, + "ownerReferences": []interface{}{ + map[string]interface{}{ + "apiVersion": ps.GetGroupVersion().String(), + "kind": ps.GetGroupVersionKind().Kind, + "blockOwnerDeletion": true, + "controller": true, + "name": ps.Name, + "uid": string(ps.UID), + }}, + }, + "spec": map[string]interface{}{ + "scaleTargetRef": map[string]interface{}{ + "deploymentName": ra.Name, + }, + "minReplicaCount": minReplicaCount, + "maxReplicaCount": maxReplicateCount, + "cooldownPeriod": cooldownPeriod, + "pollingInterval": pollingInterval, + "triggers": []interface{}{ + map[string]interface{}{ + "type": "gcp-pubsub", + "metadata": map[string]interface{}{ + "subscriptionSize": ps.Annotations[duckv1alpha1.KedaAutoscalingSubscriptionSizeAnnotation], + "subscriptionName": ps.Status.SubscriptionID, + "credentials": "GOOGLE_APPLICATION_CREDENTIALS_JSON", + }, + }}, + }, + }, + } + return so +} diff --git a/pkg/reconciler/intevents/pullsubscription/keda/resources/scaled_object_test.go b/pkg/reconciler/intevents/pullsubscription/keda/resources/scaled_object_test.go new file mode 100644 index 0000000000..e6f48ee73d --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/keda/resources/scaled_object_test.go @@ -0,0 +1,115 @@ +/* +Copyright 2020 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + "context" + "testing" + + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription/resources" + . "github.com/google/knative-gcp/pkg/reconciler/testing" + v1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "knative.dev/pkg/apis" + + "github.com/google/go-cmp/cmp" + duckv1alpha1 "github.com/google/knative-gcp/pkg/apis/duck/v1alpha1" +) + +func newAnnotations() map[string]string { + return map[string]string{ + duckv1alpha1.AutoscalingClassAnnotation: duckv1alpha1.KEDA, + duckv1alpha1.AutoscalingMinScaleAnnotation: "0", + duckv1alpha1.AutoscalingMaxScaleAnnotation: "3", + duckv1alpha1.KedaAutoscalingSubscriptionSizeAnnotation: "5", + duckv1alpha1.KedaAutoscalingCooldownPeriodAnnotation: "60", + duckv1alpha1.KedaAutoscalingPollingIntervalAnnotation: "30", + } +} + +func newPullSubscription() *v1alpha1.PullSubscription { + return NewPullSubscription("psname", "psnamespace", + WithPullSubscriptionUID("psuid"), + WithPullSubscriptionAnnotations(newAnnotations()), + WithPullSubscriptionSubscriptionID("subscriptionId"), + ) +} + +func newReceiveAdapter(ps *v1alpha1.PullSubscription) *v1.Deployment { + raArgs := &resources.ReceiveAdapterArgs{ + Image: "image", + Source: ps, + Labels: resources.GetLabels("agentName", "psName"), + SubscriptionID: "subscriptionId", + SinkURI: apis.HTTP("sinkURI"), + } + return resources.MakeReceiveAdapter(context.Background(), raArgs) +} + +func TestMakeScaledObject(t *testing.T) { + + ps := newPullSubscription() + ra := newReceiveAdapter(ps) + + want := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "keda.k8s.io/v1alpha1", + "kind": "ScaledObject", + "metadata": map[string]interface{}{ + "namespace": "psnamespace", + "name": GenerateScaledObjectName(ps), + "labels": map[string]interface{}{ + "deploymentName": ra.Name, + "events.cloud.google.com/ps-name": ps.Name, + }, + "ownerReferences": []interface{}{ + map[string]interface{}{ + "apiVersion": "internal.events.cloud.google.com/v1alpha1", + "kind": "PullSubscription", + "blockOwnerDeletion": true, + "controller": true, + "name": ps.Name, + "uid": string(ps.UID), + }}, + }, + "spec": map[string]interface{}{ + "scaleTargetRef": map[string]interface{}{ + "deploymentName": ra.Name, + }, + "minReplicaCount": int64(0), + "maxReplicaCount": int64(3), + "cooldownPeriod": int64(60), + "pollingInterval": int64(30), + "triggers": []interface{}{ + map[string]interface{}{ + "type": "gcp-pubsub", + "metadata": map[string]interface{}{ + "subscriptionSize": "5", + "subscriptionName": "subscriptionId", + "credentials": "GOOGLE_APPLICATION_CREDENTIALS_JSON", + }, + }}, + }, + }, + } + + got := MakeScaledObject(context.Background(), ra, ps) + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("unexpected (-want, +got) = %v", diff) + } +} diff --git a/pkg/reconciler/intevents/pullsubscription/reconciler.go b/pkg/reconciler/intevents/pullsubscription/reconciler.go new file mode 100644 index 0000000000..f68912b083 --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/reconciler.go @@ -0,0 +1,415 @@ +/* +Copyright 2020 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package pullsubscription + +import ( + "context" + "fmt" + "time" + + "go.uber.org/zap" + + "github.com/google/knative-gcp/pkg/utils" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + appsv1listers "k8s.io/client-go/listers/apps/v1" + corev1listers "k8s.io/client-go/listers/core/v1" + + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" + "knative.dev/pkg/logging" + "knative.dev/pkg/metrics" + "knative.dev/pkg/reconciler" + "knative.dev/pkg/resolver" + tracingconfig "knative.dev/pkg/tracing/config" + + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + listers "github.com/google/knative-gcp/pkg/client/listers/intevents/v1alpha1" + gpubsub "github.com/google/knative-gcp/pkg/gclient/pubsub" + "github.com/google/knative-gcp/pkg/reconciler/identity" + "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription/resources" + "github.com/google/knative-gcp/pkg/reconciler/pubsub" + "github.com/google/knative-gcp/pkg/tracing" +) + +const ( + // Component names for metrics. + sourceComponent = "source" + channelComponent = "channel" + + deletePubSubFailedReason = "SubscriptionDeleteFailed" + deleteWorkloadIdentityFailed = "WorkloadIdentityDeleteFailed" + reconciledPubSubFailedReason = "SubscriptionReconcileFailed" + reconciledDataPlaneFailedReason = "DataPlaneReconcileFailed" + reconciledSuccessReason = "PullSubscriptionReconciled" + workloadIdentityFailed = "WorkloadIdentityReconcileFailed" +) + +// Base implements the core controller logic for pullsubscription. +type Base struct { + *pubsub.PubSubBase + // identity reconciler for reconciling workload identity. + *identity.Identity + // DeploymentLister index properties about deployments. + DeploymentLister appsv1listers.DeploymentLister + // PullSubscriptionLister index properties about pullsubscriptions. + PullSubscriptionLister listers.PullSubscriptionLister + // serviceAccountLister for reading serviceAccounts. + ServiceAccountLister corev1listers.ServiceAccountLister + + UriResolver *resolver.URIResolver + + ReceiveAdapterImage string + ControllerAgentName string + ResourceGroup string + + LoggingConfig *logging.Config + MetricsConfig *metrics.ExporterOptions + TracingConfig *tracingconfig.Config + + // CreateClientFn is the function used to create the Pub/Sub client that interacts with Pub/Sub. + // This is needed so that we can inject a mock client for UTs purposes. + CreateClientFn gpubsub.CreateFn + + // ReconcileDataPlaneFn is the function used to reconcile the data plane resources. + ReconcileDataPlaneFn ReconcileDataPlaneFunc +} + +// ReconcileDataPlaneFunc is used to reconcile the data plane component(s). +type ReconcileDataPlaneFunc func(ctx context.Context, d *appsv1.Deployment, ps *v1alpha1.PullSubscription) error + +func (r *Base) ReconcileKind(ctx context.Context, ps *v1alpha1.PullSubscription) reconciler.Event { + ctx = logging.WithLogger(ctx, r.Logger.With(zap.Any("pullsubscription", ps))) + + ps.Status.InitializeConditions() + ps.Status.ObservedGeneration = ps.Generation + + // If pullsubscription doesn't have ownerReference and GCP ServiceAccount is provided, reconcile workload identity. + // Otherwise, its owner will reconcile workload identity. + if (ps.OwnerReferences == nil || len(ps.OwnerReferences) == 0) && ps.Spec.GoogleServiceAccount != "" { + if _, err := r.Identity.ReconcileWorkloadIdentity(ctx, ps.Spec.Project, ps); err != nil { + return reconciler.NewEvent(corev1.EventTypeWarning, workloadIdentityFailed, "Failed to reconcile Pub/Sub subscription workload identity: %s", err.Error()) + } + } + + // Sink is required. + sinkURI, err := r.resolveDestination(ctx, ps.Spec.Sink, ps) + if err != nil { + ps.Status.MarkNoSink("InvalidSink", err.Error()) + return reconciler.NewEvent(corev1.EventTypeWarning, "InvalidSink", "InvalidSink: %s", err.Error()) + } else { + ps.Status.MarkSink(sinkURI) + } + + // Transformer is optional. + if ps.Spec.Transformer != nil { + transformerURI, err := r.resolveDestination(ctx, *ps.Spec.Transformer, ps) + if err != nil { + ps.Status.MarkNoTransformer("InvalidTransformer", err.Error()) + } else { + ps.Status.MarkTransformer(transformerURI) + } + } else { + // If the transformer is nil, mark is as nil and clean up the URI. + ps.Status.MarkNoTransformer("TransformerNil", "Transformer is nil") + ps.Status.TransformerURI = nil + } + + subscriptionID, err := r.reconcileSubscription(ctx, ps) + if err != nil { + ps.Status.MarkNoSubscription(reconciledPubSubFailedReason, "Failed to reconcile Pub/Sub subscription: %s", err.Error()) + return reconciler.NewEvent(corev1.EventTypeWarning, reconciledPubSubFailedReason, "Failed to reconcile Pub/Sub subscription: %s", err.Error()) + } + ps.Status.MarkSubscribed(subscriptionID) + + err = r.reconcileDataPlaneResources(ctx, ps, r.ReconcileDataPlaneFn) + if err != nil { + ps.Status.MarkNotDeployed(reconciledDataPlaneFailedReason, "Failed to reconcile Data Plane resource(s): %s", err.Error()) + return reconciler.NewEvent(corev1.EventTypeWarning, reconciledDataPlaneFailedReason, "Failed to reconcile Data Plane resource(s): %s", err.Error()) + } + ps.Status.MarkDeployed() + + return reconciler.NewEvent(corev1.EventTypeNormal, reconciledSuccessReason, `PullSubscription reconciled: "%s/%s"`, ps.Namespace, ps.Name) +} + +func (r *Base) reconcileSubscription(ctx context.Context, ps *v1alpha1.PullSubscription) (string, error) { + if ps.Status.ProjectID == "" { + projectID, err := utils.ProjectID(ps.Spec.Project) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to find project id", zap.Error(err)) + return "", err + } + // Set the projectID in the status. + ps.Status.ProjectID = projectID + } + + // Auth to GCP is handled by having the GOOGLE_APPLICATION_CREDENTIALS environment variable + // pointing at a credential file. + client, err := r.CreateClientFn(ctx, ps.Status.ProjectID) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to create Pub/Sub client", zap.Error(err)) + return "", err + } + defer client.Close() + + // Generate the subscription name + subID := resources.GenerateSubscriptionName(ps) + + // Load the subscription. + sub := client.Subscription(subID) + subExists, err := sub.Exists(ctx) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to verify Pub/Sub subscription exists", zap.Error(err)) + return "", err + } + + t := client.Topic(ps.Spec.Topic) + topicExists, err := t.Exists(ctx) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to verify Pub/Sub topic exists", zap.Error(err)) + return "", err + } + + if !topicExists { + return "", fmt.Errorf("Topic %q does not exist", ps.Spec.Topic) + } + + // subConfig is the wanted config based on settings. + subConfig := gpubsub.SubscriptionConfig{ + Topic: t, + RetainAckedMessages: ps.Spec.RetainAckedMessages, + } + + if ps.Spec.AckDeadline != nil { + ackDeadline, err := time.ParseDuration(*ps.Spec.AckDeadline) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Invalid ackDeadline", zap.String("ackDeadline", *ps.Spec.AckDeadline)) + return "", fmt.Errorf("invalid ackDeadline: %w", err) + } + subConfig.AckDeadline = ackDeadline + } + + if ps.Spec.RetentionDuration != nil { + retentionDuration, err := time.ParseDuration(*ps.Spec.RetentionDuration) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Invalid retentionDuration", zap.String("retentionDuration", *ps.Spec.RetentionDuration)) + return "", fmt.Errorf("invalid retentionDuration: %w", err) + } + subConfig.RetentionDuration = retentionDuration + } + + // If the subscription doesn't exist, create it. + if !subExists { + // Create a new subscription to the previous topic with the given name. + sub, err = client.CreateSubscription(ctx, subID, subConfig) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to create subscription", zap.Error(err)) + return "", err + } + } + // TODO update the subscription's config if needed. + return subID, nil +} + +// deleteSubscription looks at the status.SubscriptionID and if non-empty, +// hence indicating that we have created a subscription successfully +// in the PullSubscription, remove it. +func (r *Base) deleteSubscription(ctx context.Context, ps *v1alpha1.PullSubscription) error { + if ps.Status.SubscriptionID == "" { + return nil + } + + // At this point the project ID should have been populated in the status. + // Querying Pub/Sub as the subscription could have been deleted outside the cluster (e.g, through gcloud). + client, err := r.CreateClientFn(ctx, ps.Status.ProjectID) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to create Pub/Sub client", zap.Error(err)) + return err + } + defer client.Close() + + // Load the subscription. + sub := client.Subscription(ps.Status.SubscriptionID) + exists, err := sub.Exists(ctx) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to verify Pub/Sub subscription exists", zap.Error(err)) + return err + } + if exists { + if err := sub.Delete(ctx); err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to delete Pub/Sub subscription", zap.Error(err)) + return err + } + } + return nil +} + +func (r *Base) reconcileDataPlaneResources(ctx context.Context, src *v1alpha1.PullSubscription, f ReconcileDataPlaneFunc) error { + loggingConfig, err := logging.LoggingConfigToJson(r.LoggingConfig) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Error serializing existing logging config", zap.Error(err)) + } + + if r.MetricsConfig != nil { + component := sourceComponent + // Set the metric component based on the channel label. + if _, ok := src.Labels["events.cloud.google.com/channel"]; ok { + component = channelComponent + } + r.MetricsConfig.Component = component + } + + metricsConfig, err := metrics.MetricsOptionsToJson(r.MetricsConfig) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Error serializing metrics config", zap.Error(err)) + } + + tracingConfig, err := tracing.ConfigToJSON(r.TracingConfig) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Error serializing tracing config", zap.Error(err)) + } + + desired := resources.MakeReceiveAdapter(ctx, &resources.ReceiveAdapterArgs{ + Image: r.ReceiveAdapterImage, + Source: src, + Labels: resources.GetLabels(r.ControllerAgentName, src.Name), + SubscriptionID: src.Status.SubscriptionID, + SinkURI: src.Status.SinkURI, + TransformerURI: src.Status.TransformerURI, + LoggingConfig: loggingConfig, + MetricsConfig: metricsConfig, + TracingConfig: tracingConfig, + }) + + return f(ctx, desired, src) +} + +func (r *Base) GetOrCreateReceiveAdapter(ctx context.Context, desired *appsv1.Deployment, src *v1alpha1.PullSubscription) (*appsv1.Deployment, error) { + existing, err := r.getReceiveAdapter(ctx, src) + if err != nil && !apierrors.IsNotFound(err) { + logging.FromContext(ctx).Desugar().Error("Unable to get an existing Receive Adapter", zap.Error(err)) + return nil, err + } + if existing == nil { + existing, err = r.KubeClientSet.AppsV1().Deployments(src.Namespace).Create(desired) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Error creating Receive Adapter", zap.Error(err)) + return nil, err + } + } + return existing, nil +} + +func (r *Base) getReceiveAdapter(ctx context.Context, src *v1alpha1.PullSubscription) (*appsv1.Deployment, error) { + dl, err := r.KubeClientSet.AppsV1().Deployments(src.Namespace).List(metav1.ListOptions{ + LabelSelector: resources.GetLabelSelector(r.ControllerAgentName, src.Name).String(), + TypeMeta: metav1.TypeMeta{ + APIVersion: appsv1.SchemeGroupVersion.String(), + Kind: "Deployment", + }, + }) + + if err != nil { + logging.FromContext(ctx).Desugar().Error("Unable to list deployments", zap.Error(err)) + return nil, err + } + for _, dep := range dl.Items { + if metav1.IsControlledBy(&dep, src) { + return &dep, nil + } + } + return nil, apierrors.NewNotFound(schema.GroupResource{}, "") +} + +func (r *Base) UpdateFromLoggingConfigMap(cfg *corev1.ConfigMap) { + if cfg != nil { + delete(cfg.Data, "_example") + } + + logcfg, err := logging.NewConfigFromConfigMap(cfg) + if err != nil { + r.Logger.Warnw("Failed to create logging config from configmap", zap.String("cfg.Name", cfg.Name)) + return + } + r.LoggingConfig = logcfg + r.Logger.Debugw("Update from logging ConfigMap", zap.Any("loggingCfg", cfg)) + // TODO: requeue all PullSubscriptions. See https://github.com/google/knative-gcp/issues/457. +} + +func (r *Base) UpdateFromMetricsConfigMap(cfg *corev1.ConfigMap) { + if cfg != nil { + delete(cfg.Data, "_example") + } + + // Cannot set the component here as we don't know if its a source or a channel. + // Will set that up dynamically before creating the receive adapter. + // Won't be able to requeue the PullSubscriptions. + r.MetricsConfig = &metrics.ExporterOptions{ + Domain: metrics.Domain(), + ConfigMap: cfg.Data, + } + r.Logger.Debugw("Update from metrics ConfigMap", zap.Any("metricsCfg", cfg)) +} + +func (r *Base) UpdateFromTracingConfigMap(cfg *corev1.ConfigMap) { + if cfg == nil { + r.Logger.Error("Tracing ConfigMap is nil") + return + } + delete(cfg.Data, "_example") + + tracingCfg, err := tracingconfig.NewTracingConfigFromConfigMap(cfg) + if err != nil { + r.Logger.Warnw("Failed to create tracing config from configmap", zap.String("cfg.Name", cfg.Name)) + return + } + r.TracingConfig = tracingCfg + r.Logger.Debugw("Updated Tracing config", zap.Any("tracingCfg", r.TracingConfig)) + // TODO: requeue all PullSubscriptions. See https://github.com/google/knative-gcp/issues/457. +} + +func (r *Base) resolveDestination(ctx context.Context, destination duckv1.Destination, ps *v1alpha1.PullSubscription) (*apis.URL, error) { + // Setting up the namespace. + if destination.Ref != nil { + destination.Ref.Namespace = ps.Namespace + } + url, err := r.UriResolver.URIFromDestinationV1(destination, ps) + if err != nil { + return nil, err + } + return url, nil +} + +func (r *Base) FinalizeKind(ctx context.Context, ps *v1alpha1.PullSubscription) reconciler.Event { + // If pullsubscription doesn't have ownerReference, k8s ServiceAccount exists and it only has one ownerReference, remove the corresponding GCP ServiceAccount iam policy binding. + // No need to delete k8s ServiceAccount, it will be automatically handled by k8s Garbage Collection. + if (ps.OwnerReferences == nil || len(ps.OwnerReferences) == 0) && ps.Spec.GoogleServiceAccount != "" { + if err := r.Identity.DeleteWorkloadIdentity(ctx, ps.Spec.Project, ps); err != nil { + return reconciler.NewEvent(corev1.EventTypeWarning, deleteWorkloadIdentityFailed, "Failed to delete delete Pub/Sub subscription workload identity: %s", err.Error()) + } + } + + logging.FromContext(ctx).Desugar().Debug("Deleting Pub/Sub subscription") + if err := r.deleteSubscription(ctx, ps); err != nil { + return reconciler.NewEvent(corev1.EventTypeWarning, deletePubSubFailedReason, "Failed to delete Pub/Sub subscription: %s", err.Error()) + } + ps.Status.SubscriptionID = "" + return nil +} diff --git a/pkg/reconciler/intevents/pullsubscription/resources/labels.go b/pkg/reconciler/intevents/pullsubscription/resources/labels.go new file mode 100644 index 0000000000..0e6db41fdf --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/resources/labels.go @@ -0,0 +1,32 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + "k8s.io/apimachinery/pkg/labels" +) + +func GetLabelSelector(controller, source string) labels.Selector { + return labels.SelectorFromSet(GetLabels(controller, source)) +} + +func GetLabels(controller, source string) map[string]string { + return map[string]string{ + "events.cloud.google.com/controller": controller, + "internal.events.cloud.google.com/pullsubscription": source, + } +} diff --git a/pkg/reconciler/intevents/pullsubscription/resources/names.go b/pkg/reconciler/intevents/pullsubscription/resources/names.go new file mode 100644 index 0000000000..3cff5ee03b --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/resources/names.go @@ -0,0 +1,27 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + "fmt" + + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" +) + +func GenerateSubscriptionName(src *v1alpha1.PullSubscription) string { + return fmt.Sprintf("cre-pull-%s", string(src.UID)) +} diff --git a/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter.go b/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter.go new file mode 100644 index 0000000000..1190e845ac --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter.go @@ -0,0 +1,228 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + "context" + "fmt" + + "go.uber.org/zap" + + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" + "github.com/google/knative-gcp/pkg/reconciler/identity/resources" + "github.com/google/knative-gcp/pkg/utils" + "knative.dev/pkg/apis" + "knative.dev/pkg/kmeta" + "knative.dev/pkg/logging" + + v1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ReceiveAdapterArgs are the arguments needed to create a PullSubscription Receive +// Adapter. Every field is required. +type ReceiveAdapterArgs struct { + Image string + Source *v1alpha1.PullSubscription + Labels map[string]string + SubscriptionID string + SinkURI *apis.URL + TransformerURI *apis.URL + MetricsConfig string + LoggingConfig string + TracingConfig string +} + +const ( + credsVolume = "google-cloud-key" + credsMountPath = "/var/secrets/google" + metricsDomain = "cloud.google.com/events" + defaultResourceGroup = "pullsubscriptions.internal.events.cloud.google.com" +) + +func makeReceiveAdapterPodSpec(ctx context.Context, args *ReceiveAdapterArgs) *corev1.PodSpec { + // Convert CloudEvent Overrides to pod embeddable properties. + ceExtensions := "" + if args.Source.Spec.CloudEventOverrides != nil && args.Source.Spec.CloudEventOverrides.Extensions != nil { + var err error + ceExtensions, err = utils.MapToBase64(args.Source.Spec.CloudEventOverrides.Extensions) + if err != nil { + logging.FromContext(ctx).Warnw("failed to make cloudevents overrides extensions", + zap.Error(err), + zap.Any("extensions", args.Source.Spec.CloudEventOverrides.Extensions)) + } + } + + var mode converters.ModeType + switch args.Source.PubSubMode() { + case "", v1alpha1.ModeCloudEventsBinary: + mode = converters.Binary + case v1alpha1.ModeCloudEventsStructured: + mode = converters.Structured + case v1alpha1.ModePushCompatible: + mode = converters.Push + } + + var resourceGroup = defaultResourceGroup + if rg, ok := args.Source.Annotations["metrics-resource-group"]; ok { + resourceGroup = rg + } + // Needed for Channels, as we use a generate name for the PullSubscription. + var resourceName = args.Source.Name + if rn, ok := args.Source.Annotations["metrics-resource-name"]; ok { + resourceName = rn + } + + var transformerURI string + if args.TransformerURI != nil { + transformerURI = args.TransformerURI.String() + } + + receiveAdapterContainer := corev1.Container{ + Name: "receive-adapter", + Image: args.Image, + Env: []corev1.EnvVar{{ + Name: "PROJECT_ID", + Value: args.Source.Spec.Project, + }, { + Name: "PUBSUB_TOPIC_ID", + Value: args.Source.Spec.Topic, + }, { + Name: "PUBSUB_SUBSCRIPTION_ID", + Value: args.SubscriptionID, + }, { + Name: "SINK_URI", + Value: args.SinkURI.String(), + }, { + Name: "TRANSFORMER_URI", + Value: transformerURI, + }, { + Name: "ADAPTER_TYPE", + Value: args.Source.Spec.AdapterType, + }, { + Name: "SEND_MODE", + Value: string(mode), + }, { + Name: "K_CE_EXTENSIONS", + Value: ceExtensions, + }, { + Name: "K_METRICS_CONFIG", + Value: args.MetricsConfig, + }, { + Name: "K_LOGGING_CONFIG", + Value: args.LoggingConfig, + }, { + Name: "K_TRACING_CONFIG", + Value: args.TracingConfig, + }, { + Name: "NAME", + Value: resourceName, + }, { + Name: "NAMESPACE", + Value: args.Source.Namespace, + }, { + Name: "RESOURCE_GROUP", + Value: resourceGroup, + }, { + Name: "METRICS_DOMAIN", + Value: metricsDomain, + }}, + Ports: []corev1.ContainerPort{{ + Name: "metrics", + ContainerPort: 9090, + }}, + } + + // If GCP service account is specified, use that service account as credential. + if args.Source.Spec.GoogleServiceAccount != "" { + kServiceAccountName := resources.GenerateServiceAccountName(args.Source.Spec.GoogleServiceAccount) + return &corev1.PodSpec{ + ServiceAccountName: kServiceAccountName, + Containers: []corev1.Container{ + receiveAdapterContainer, + }, + } + } + + // Otherwise, use secret as credential. + secret := args.Source.Spec.Secret + credsFile := fmt.Sprintf("%s/%s", credsMountPath, secret.Key) + + receiveAdapterContainer.Env = append( + receiveAdapterContainer.Env, + corev1.EnvVar{ + Name: "GOOGLE_APPLICATION_CREDENTIALS", + Value: credsFile, + }, + corev1.EnvVar{ + // Needed for Keda scaling. + // TODO set it only when using Keda. + Name: "GOOGLE_APPLICATION_CREDENTIALS_JSON", + ValueFrom: &corev1.EnvVarSource{SecretKeyRef: secret}, + }) + + receiveAdapterContainer.VolumeMounts = []corev1.VolumeMount{{ + Name: credsVolume, + MountPath: credsMountPath, + }} + + return &corev1.PodSpec{ + Containers: []corev1.Container{ + receiveAdapterContainer, + }, + Volumes: []corev1.Volume{{ + Name: credsVolume, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: secret.Name, + }, + }, + }}, + } +} + +// MakeReceiveAdapter generates (but does not insert into K8s) the Receive Adapter Deployment for +// PullSubscriptions. +func MakeReceiveAdapter(ctx context.Context, args *ReceiveAdapterArgs) *v1.Deployment { + podSpec := makeReceiveAdapterPodSpec(ctx, args) + replicas := int32(1) + + return &v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: args.Source.Namespace, + Name: GenerateSubscriptionName(args.Source), + Labels: args.Labels, + OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(args.Source)}, + // Copy the source annotations so that the appropriate reconciler is called. + Annotations: args.Source.Annotations, + }, + Spec: v1.DeploymentSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: args.Labels, + }, + Replicas: &replicas, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: args.Labels, + }, + Spec: *podSpec, + }, + }, + } +} diff --git a/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go b/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go new file mode 100644 index 0000000000..c21a21f027 --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go @@ -0,0 +1,489 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + duckv1alpha1 "github.com/google/knative-gcp/pkg/apis/duck/v1alpha1" + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + v1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +func TestMakeMinimumReceiveAdapter(t *testing.T) { + src := &v1alpha1.PullSubscription{ + ObjectMeta: metav1.ObjectMeta{ + Name: "source-name", + Namespace: "source-namespace", + }, + Spec: v1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "eventing-secret-name", + }, + Key: "eventing-secret-key", + }, + Project: "eventing-name", + }, + Topic: "topic", + }, + } + + got := MakeReceiveAdapter(context.Background(), &ReceiveAdapterArgs{ + Image: "test-image", + Source: src, + Labels: map[string]string{ + "test-key1": "test-value1", + "test-key2": "test-value2", + }, + SubscriptionID: "sub-id", + SinkURI: apis.HTTP("sink-uri"), + LoggingConfig: "LoggingConfig-ABC123", + MetricsConfig: "MetricsConfig-ABC123", + TracingConfig: "TracingConfig-ABC123", + }) + + one := int32(1) + yes := true + want := &v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "source-namespace", + Name: "cre-pull-", + Annotations: nil, + Labels: map[string]string{ + "test-key1": "test-value1", + "test-key2": "test-value2", + }, + OwnerReferences: []metav1.OwnerReference{{ + APIVersion: "internal.events.cloud.google.com/v1alpha1", + Kind: "PullSubscription", + Name: "source-name", + Controller: &yes, + BlockOwnerDeletion: &yes, + }}, + }, + Spec: v1.DeploymentSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "test-key1": "test-value1", + "test-key2": "test-value2", + }, + }, + Replicas: &one, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "test-key1": "test-value1", + "test-key2": "test-value2", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Name: "receive-adapter", + Image: "test-image", + Env: []corev1.EnvVar{{ + Name: "PROJECT_ID", + Value: "eventing-name", + }, { + Name: "PUBSUB_TOPIC_ID", + Value: "topic", + }, { + Name: "PUBSUB_SUBSCRIPTION_ID", + Value: "sub-id", + }, { + Name: "SINK_URI", + Value: "http://sink-uri", + }, { + Name: "TRANSFORMER_URI", + }, { + Name: "ADAPTER_TYPE", + }, { + Name: "SEND_MODE", + Value: "binary", + }, { + Name: "K_CE_EXTENSIONS", + }, { + Name: "K_METRICS_CONFIG", + Value: "MetricsConfig-ABC123", + }, { + Name: "K_LOGGING_CONFIG", + Value: "LoggingConfig-ABC123", + }, { + Name: "K_TRACING_CONFIG", + Value: "TracingConfig-ABC123", + }, { + Name: "NAME", + Value: "source-name", + }, { + Name: "NAMESPACE", + Value: "source-namespace", + }, { + Name: "RESOURCE_GROUP", + Value: defaultResourceGroup, + }, { + Name: "METRICS_DOMAIN", + Value: metricsDomain, + }, { + Name: "GOOGLE_APPLICATION_CREDENTIALS", + Value: "/var/secrets/google/eventing-secret-key", + }, { + Name: "GOOGLE_APPLICATION_CREDENTIALS_JSON", + ValueFrom: &corev1.EnvVarSource{SecretKeyRef: src.Spec.Secret}, + }}, + VolumeMounts: []corev1.VolumeMount{{ + Name: credsVolume, + MountPath: credsMountPath, + }}, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 9090}}, + }}, + Volumes: []corev1.Volume{{ + Name: credsVolume, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "eventing-secret-name", + }, + }, + }}, + }, + }, + }, + } + + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("unexpected deploy (-want, +got) = %v", diff) + } +} + +func TestMakeFullReceiveAdapter(t *testing.T) { + src := &v1alpha1.PullSubscription{ + ObjectMeta: metav1.ObjectMeta{ + Name: "source-name", + Namespace: "source-namespace", + Annotations: map[string]string{ + "metrics-resource-group": "test-resource-group", + }, + }, + Spec: v1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "eventing-secret-name", + }, + Key: "eventing-secret-key", + }, + Project: "eventing-name", + SourceSpec: duckv1.SourceSpec{ + CloudEventOverrides: &duckv1.CloudEventOverrides{ + Extensions: map[string]string{ + "foo": "bar", // base64 value is eyJmb28iOiJiYXIifQ== + }, + }, + }, + }, + Topic: "topic", + AdapterType: "adapter-type", + }, + } + + got := MakeReceiveAdapter(context.Background(), &ReceiveAdapterArgs{ + Image: "test-image", + Source: src, + Labels: map[string]string{ + "test-key1": "test-value1", + "test-key2": "test-value2", + }, + SubscriptionID: "sub-id", + SinkURI: apis.HTTP("sink-uri"), + TransformerURI: apis.HTTP("transformer-uri"), + LoggingConfig: "LoggingConfig-ABC123", + MetricsConfig: "MetricsConfig-ABC123", + TracingConfig: "TracingConfig-ABC123", + }) + + one := int32(1) + yes := true + want := &v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "source-namespace", + Name: "cre-pull-", + Annotations: src.Annotations, + Labels: map[string]string{ + "test-key1": "test-value1", + "test-key2": "test-value2", + }, + OwnerReferences: []metav1.OwnerReference{{ + APIVersion: "internal.events.cloud.google.com/v1alpha1", + Kind: "PullSubscription", + Name: "source-name", + Controller: &yes, + BlockOwnerDeletion: &yes, + }}, + }, + Spec: v1.DeploymentSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "test-key1": "test-value1", + "test-key2": "test-value2", + }, + }, + Replicas: &one, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "test-key1": "test-value1", + "test-key2": "test-value2", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Name: "receive-adapter", + Image: "test-image", + Env: []corev1.EnvVar{{ + Name: "PROJECT_ID", + Value: "eventing-name", + }, { + Name: "PUBSUB_TOPIC_ID", + Value: "topic", + }, { + Name: "PUBSUB_SUBSCRIPTION_ID", + Value: "sub-id", + }, { + Name: "SINK_URI", + Value: "http://sink-uri", + }, { + Name: "TRANSFORMER_URI", + Value: "http://transformer-uri", + }, { + Name: "ADAPTER_TYPE", + Value: "adapter-type", + }, { + Name: "SEND_MODE", + Value: "binary", + }, { + Name: "K_CE_EXTENSIONS", + Value: "eyJmb28iOiJiYXIifQ==", + }, { + Name: "K_METRICS_CONFIG", + Value: "MetricsConfig-ABC123", + }, { + Name: "K_LOGGING_CONFIG", + Value: "LoggingConfig-ABC123", + }, { + Name: "K_TRACING_CONFIG", + Value: "TracingConfig-ABC123", + }, { + Name: "NAME", + Value: "source-name", + }, { + Name: "NAMESPACE", + Value: "source-namespace", + }, { + Name: "RESOURCE_GROUP", + Value: "test-resource-group", + }, { + Name: "METRICS_DOMAIN", + Value: metricsDomain, + }, { + Name: "GOOGLE_APPLICATION_CREDENTIALS", + Value: "/var/secrets/google/eventing-secret-key", + }, { + Name: "GOOGLE_APPLICATION_CREDENTIALS_JSON", + ValueFrom: &corev1.EnvVarSource{SecretKeyRef: src.Spec.Secret}, + }}, + VolumeMounts: []corev1.VolumeMount{{ + Name: credsVolume, + MountPath: credsMountPath, + }}, + Ports: []corev1.ContainerPort{{ + Name: "metrics", + ContainerPort: 9090, + }}, + }}, + Volumes: []corev1.Volume{{ + Name: credsVolume, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "eventing-secret-name", + }, + }, + }}, + }, + }, + }, + } + + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("unexpected deploy (-want, +got) = %v", diff) + } +} + +func TestMakeReceiveAdapterWithGCPServiceAccount(t *testing.T) { + gServiceAccountName := "test@test.iam.gserviceaccount.com" + src := &v1alpha1.PullSubscription{ + ObjectMeta: metav1.ObjectMeta{ + Name: "source-name", + Namespace: "source-namespace", + Annotations: map[string]string{ + "metrics-resource-group": "test-resource-group", + }, + }, + Spec: v1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + IdentitySpec: duckv1alpha1.IdentitySpec{ + GoogleServiceAccount: gServiceAccountName, + }, + Secret: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "eventing-secret-name", + }, + Key: "eventing-secret-key", + }, + Project: "eventing-name", + SourceSpec: duckv1.SourceSpec{ + CloudEventOverrides: &duckv1.CloudEventOverrides{ + Extensions: map[string]string{ + "foo": "bar", // base64 value is eyJmb28iOiJiYXIifQ== + }, + }, + }, + }, + Topic: "topic", + AdapterType: "adapter-type", + }, + } + + got := MakeReceiveAdapter(context.Background(), &ReceiveAdapterArgs{ + Image: "test-image", + Source: src, + Labels: map[string]string{ + "test-key1": "test-value1", + "test-key2": "test-value2", + }, + SubscriptionID: "sub-id", + SinkURI: apis.HTTP("sink-uri"), + TransformerURI: apis.HTTP("transformer-uri"), + LoggingConfig: "LoggingConfig-ABC123", + MetricsConfig: "MetricsConfig-ABC123", + TracingConfig: "TracingConfig-ABC123", + }) + + one := int32(1) + yes := true + want := &v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "source-namespace", + Name: "cre-pull-", + Annotations: src.Annotations, + Labels: map[string]string{ + "test-key1": "test-value1", + "test-key2": "test-value2", + }, + OwnerReferences: []metav1.OwnerReference{{ + APIVersion: "internal.events.cloud.google.com/v1alpha1", + Kind: "PullSubscription", + Name: "source-name", + Controller: &yes, + BlockOwnerDeletion: &yes, + }}, + }, + Spec: v1.DeploymentSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "test-key1": "test-value1", + "test-key2": "test-value2", + }, + }, + Replicas: &one, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "test-key1": "test-value1", + "test-key2": "test-value2", + }, + }, + Spec: corev1.PodSpec{ + ServiceAccountName: "test", + Containers: []corev1.Container{{ + Name: "receive-adapter", + Image: "test-image", + Env: []corev1.EnvVar{{ + Name: "PROJECT_ID", + Value: "eventing-name", + }, { + Name: "PUBSUB_TOPIC_ID", + Value: "topic", + }, { + Name: "PUBSUB_SUBSCRIPTION_ID", + Value: "sub-id", + }, { + Name: "SINK_URI", + Value: "http://sink-uri", + }, { + Name: "TRANSFORMER_URI", + Value: "http://transformer-uri", + }, { + Name: "ADAPTER_TYPE", + Value: "adapter-type", + }, { + Name: "SEND_MODE", + Value: "binary", + }, { + Name: "K_CE_EXTENSIONS", + Value: "eyJmb28iOiJiYXIifQ==", + }, { + Name: "K_METRICS_CONFIG", + Value: "MetricsConfig-ABC123", + }, { + Name: "K_LOGGING_CONFIG", + Value: "LoggingConfig-ABC123", + }, { + Name: "K_TRACING_CONFIG", + Value: "TracingConfig-ABC123", + }, { + Name: "NAME", + Value: "source-name", + }, { + Name: "NAMESPACE", + Value: "source-namespace", + }, { + Name: "RESOURCE_GROUP", + Value: "test-resource-group", + }, { + Name: "METRICS_DOMAIN", + Value: metricsDomain, + }}, + Ports: []corev1.ContainerPort{{ + Name: "metrics", + ContainerPort: 9090, + }}, + }}, + }, + }, + }, + } + + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("unexpected deploy (-want, +got) = %v", diff) + } +} diff --git a/pkg/reconciler/intevents/pullsubscription/static/controller.go b/pkg/reconciler/intevents/pullsubscription/static/controller.go new file mode 100644 index 0000000000..babbce5a7a --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/static/controller.go @@ -0,0 +1,142 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package static + +import ( + "context" + + duckv1alpha1 "github.com/google/knative-gcp/pkg/apis/duck/v1alpha1" + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + pullsubscriptioninformers "github.com/google/knative-gcp/pkg/client/injection/informers/intevents/v1alpha1/pullsubscription" + gpubsub "github.com/google/knative-gcp/pkg/gclient/pubsub" + "github.com/google/knative-gcp/pkg/reconciler" + "github.com/google/knative-gcp/pkg/reconciler/identity" + "github.com/google/knative-gcp/pkg/reconciler/identity/iam" + psreconciler "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription" + "github.com/google/knative-gcp/pkg/reconciler/pubsub" + "github.com/kelseyhightower/envconfig" + "go.uber.org/zap" + "k8s.io/client-go/tools/cache" + + pullsubscriptionreconciler "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription" + deploymentinformer "knative.dev/pkg/client/injection/kube/informers/apps/v1/deployment" + serviceaccountinformers "knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount" + "knative.dev/pkg/configmap" + "knative.dev/pkg/controller" + "knative.dev/pkg/logging" + "knative.dev/pkg/metrics" + pkgreconciler "knative.dev/pkg/reconciler" + "knative.dev/pkg/resolver" + tracingconfig "knative.dev/pkg/tracing/config" +) + +const ( + // reconcilerName is the name of the reconciler + reconcilerName = "PullSubscriptions" + + // controllerAgentName is the string used by this controller to identify + // itself when creating events. + controllerAgentName = "cloud-run-events-pubsub-pullsubscription-controller" + + resourceGroup = "pullsubscriptions.internal.events.cloud.google.com" +) + +type envConfig struct { + // ReceiveAdapter is the receive adapters image. Required. + ReceiveAdapter string `envconfig:"PUBSUB_RA_IMAGE" required:"true"` +} + +// NewController initializes the controller and is called by the generated code +// Registers event handlers to enqueue events +func NewController( + ctx context.Context, + cmw configmap.Watcher, +) *controller.Impl { + return newControllerWithIAMPolicyManager( + ctx, + cmw, + iam.DefaultIAMPolicyManager()) +} + +func newControllerWithIAMPolicyManager( + ctx context.Context, + cmw configmap.Watcher, + ipm iam.IAMPolicyManager, +) *controller.Impl { + deploymentInformer := deploymentinformer.Get(ctx) + pullSubscriptionInformer := pullsubscriptioninformers.Get(ctx) + serviceAccountInformer := serviceaccountinformers.Get(ctx) + + logger := logging.FromContext(ctx).Named(controllerAgentName).Desugar() + + var env envConfig + if err := envconfig.Process("", &env); err != nil { + logger.Fatal("Failed to process env var", zap.Error(err)) + } + + pubsubBase := &pubsub.PubSubBase{ + Base: reconciler.NewBase(ctx, controllerAgentName, cmw), + } + + r := &Reconciler{ + Base: &psreconciler.Base{ + PubSubBase: pubsubBase, + Identity: identity.NewIdentity(ctx, ipm), + DeploymentLister: deploymentInformer.Lister(), + PullSubscriptionLister: pullSubscriptionInformer.Lister(), + ReceiveAdapterImage: env.ReceiveAdapter, + CreateClientFn: gpubsub.NewClient, + ControllerAgentName: controllerAgentName, + ResourceGroup: resourceGroup, + }, + } + + impl := pullsubscriptionreconciler.NewImpl(ctx, r) + + pubsubBase.Logger.Info("Setting up event handlers") + + // Whenever we introduce a new way of scaling, this code will have to be updated to not just exclude Keda, but the others. + // Might be useful to use pkgreconciler.ChainFilterFuncs and move them somewhere else. + // TODO revisit once we introduce new scaling strategies. + onlyKedaScaler := pkgreconciler.AnnotationFilterFunc(duckv1alpha1.AutoscalingClassAnnotation, duckv1alpha1.KEDA, false) + notKedaScaler := pkgreconciler.Not(onlyKedaScaler) + + pullSubscriptionHandler := cache.FilteringResourceEventHandler{ + FilterFunc: notKedaScaler, + Handler: controller.HandleAll(impl.Enqueue), + } + pullSubscriptionInformer.Informer().AddEventHandlerWithResyncPeriod(pullSubscriptionHandler, reconciler.DefaultResyncPeriod) + + deploymentInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ + FilterFunc: notKedaScaler, + Handler: controller.HandleAll(impl.EnqueueControllerOf), + }) + + serviceAccountInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ + FilterFunc: controller.FilterGroupVersionKind(v1alpha1.SchemeGroupVersion.WithKind("Pullsubscription")), + Handler: controller.HandleAll(impl.EnqueueControllerOf), + }) + + r.UriResolver = resolver.NewURIResolver(ctx, impl.EnqueueKey) + r.ReconcileDataPlaneFn = r.ReconcileDeployment + + cmw.Watch(logging.ConfigMapName(), r.UpdateFromLoggingConfigMap) + cmw.Watch(metrics.ConfigMapName(), r.UpdateFromMetricsConfigMap) + cmw.Watch(tracingconfig.ConfigName, r.UpdateFromTracingConfigMap) + + return impl +} diff --git a/pkg/reconciler/intevents/pullsubscription/static/controller_test.go b/pkg/reconciler/intevents/pullsubscription/static/controller_test.go new file mode 100644 index 0000000000..92f3827e03 --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/static/controller_test.go @@ -0,0 +1,79 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package static + +import ( + "os" + "testing" + + iamtesting "github.com/google/knative-gcp/pkg/reconciler/testing" + "knative.dev/pkg/configmap" + "knative.dev/pkg/logging" + logtesting "knative.dev/pkg/logging/testing" + "knative.dev/pkg/metrics" + _ "knative.dev/pkg/metrics/testing" + . "knative.dev/pkg/reconciler/testing" + "knative.dev/pkg/system" + tracingconfig "knative.dev/pkg/tracing/config" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + _ "knative.dev/pkg/client/injection/ducks/duck/v1/addressable/fake" + _ "knative.dev/pkg/client/injection/kube/informers/apps/v1/deployment/fake" + _ "knative.dev/pkg/client/injection/kube/informers/batch/v1/job/fake" + _ "knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount/fake" + + // Fake injection informers + _ "github.com/google/knative-gcp/pkg/client/injection/informers/intevents/v1alpha1/pullsubscription/fake" +) + +func TestNew(t *testing.T) { + defer logtesting.ClearAll() + ctx, _ := SetupFakeContext(t) + + _ = os.Setenv("PUBSUB_RA_IMAGE", "PUBSUB_RA_IMAGE") + + c := newControllerWithIAMPolicyManager(ctx, configmap.NewStaticWatcher( + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: logging.ConfigMapName(), + Namespace: system.Namespace(), + }, + Data: map[string]string{}, + }, + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: metrics.ConfigMapName(), + Namespace: system.Namespace(), + }, + Data: map[string]string{}, + }, + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: tracingconfig.ConfigName, + Namespace: system.Namespace(), + }, + Data: map[string]string{}, + }, + ), + iamtesting.NoopIAMPolicyManager) + + if c == nil { + t.Fatal("Expected newControllerWithIAMPolicyManager to return a non-nil value") + } +} diff --git a/pkg/reconciler/intevents/pullsubscription/static/doc.go b/pkg/reconciler/intevents/pullsubscription/static/doc.go new file mode 100644 index 0000000000..a7f19f0851 --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/static/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2020 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package static implements the Pub/Sub PullSubscription controller for non-scalable PullSubscriptions. +package static diff --git a/pkg/reconciler/intevents/pullsubscription/static/pullsubscription.go b/pkg/reconciler/intevents/pullsubscription/static/pullsubscription.go new file mode 100644 index 0000000000..f48b2db30e --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/static/pullsubscription.go @@ -0,0 +1,63 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package static + +import ( + "context" + + "go.uber.org/zap" + + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + pullsubscriptionreconciler "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription" + psreconciler "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription" + appsv1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/api/equality" + "knative.dev/pkg/logging" + "knative.dev/pkg/reconciler" +) + +// Reconciler implements controller.Reconciler for PullSubscription resources. +type Reconciler struct { + *psreconciler.Base +} + +// Check that our Reconciler implements Interface. +var _ pullsubscriptionreconciler.Interface = (*Reconciler)(nil) + +func (r *Reconciler) ReconcileKind(ctx context.Context, ps *v1alpha1.PullSubscription) reconciler.Event { + return r.Base.ReconcileKind(ctx, ps) +} + +func (r *Reconciler) ReconcileDeployment(ctx context.Context, ra *appsv1.Deployment, src *v1alpha1.PullSubscription) error { + existing, err := r.Base.GetOrCreateReceiveAdapter(ctx, ra, src) + if err != nil { + return err + } + if !equality.Semantic.DeepEqual(ra.Spec, existing.Spec) { + existing.Spec = ra.Spec + _, err := r.KubeClientSet.AppsV1().Deployments(src.Namespace).Update(existing) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Error updating Receive Adapter", zap.Error(err)) + return err + } + } + return nil +} + +func (r *Reconciler) FinalizeKind(ctx context.Context, ps *v1alpha1.PullSubscription) reconciler.Event { + return r.Base.FinalizeKind(ctx, ps) +} diff --git a/pkg/reconciler/intevents/pullsubscription/static/pullsubscription_test.go b/pkg/reconciler/intevents/pullsubscription/static/pullsubscription_test.go new file mode 100644 index 0000000000..a33fba3bcd --- /dev/null +++ b/pkg/reconciler/intevents/pullsubscription/static/pullsubscription_test.go @@ -0,0 +1,827 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package static + +import ( + "context" + "errors" + "fmt" + "strings" + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes/scheme" + clientgotesting "k8s.io/client-go/testing" + "knative.dev/pkg/apis" + + "knative.dev/pkg/client/injection/ducks/duck/v1/addressable" + _ "knative.dev/pkg/client/injection/ducks/duck/v1/addressable/fake" + + "knative.dev/pkg/configmap" + "knative.dev/pkg/controller" + logtesting "knative.dev/pkg/logging/testing" + . "knative.dev/pkg/reconciler/testing" + "knative.dev/pkg/resolver" + + duckv1alpha1 "github.com/google/knative-gcp/pkg/apis/duck/v1alpha1" + pubsubv1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription" + gpubsub "github.com/google/knative-gcp/pkg/gclient/pubsub/testing" + "github.com/google/knative-gcp/pkg/reconciler" + psreconciler "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription" + "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription/resources" + "github.com/google/knative-gcp/pkg/reconciler/pubsub" + . "github.com/google/knative-gcp/pkg/reconciler/testing" +) + +const ( + sourceName = "source" + sinkName = "sink" + transformerName = "transformer" + + testNS = "testnamespace" + + testImage = "test_image" + + sourceUID = sourceName + "-abc-123" + + testProject = "test-project-id" + testTopicID = sourceUID + "-TOPIC" + testSubscriptionID = "cre-pull-" + sourceUID + generation = 1 + + secretName = "testing-secret" + + failedToReconcileSubscriptionMsg = `Failed to reconcile Pub/Sub subscription` + failedToDeleteSubscriptionMsg = `Failed to delete Pub/Sub subscription` +) + +var ( + sinkDNS = sinkName + ".mynamespace.svc.cluster.local" + sinkURI = apis.HTTP(sinkDNS) + + transformerDNS = transformerName + ".mynamespace.svc.cluster.local" + transformerURI = apis.HTTP(transformerDNS) + + sinkGVK = metav1.GroupVersionKind{ + Group: "testing.cloud.google.com", + Version: "v1alpha1", + Kind: "Sink", + } + + transformerGVK = metav1.GroupVersionKind{ + Group: "testing.cloud.google.com", + Version: "v1alpha1", + Kind: "Transformer", + } + + secret = corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: secretName, + }, + Key: "testing-key", + } +) + +func init() { + // Add types to scheme + _ = pubsubv1alpha1.AddToScheme(scheme.Scheme) +} + +func newSecret() *corev1.Secret { + return &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: testNS, + Name: secretName, + }, + Data: map[string][]byte{ + "testing-key": []byte("abcd"), + }, + } +} + +func newSink() *unstructured.Unstructured { + return &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "testing.cloud.google.com/v1alpha1", + "kind": "Sink", + "metadata": map[string]interface{}{ + "namespace": testNS, + "name": sinkName, + }, + "status": map[string]interface{}{ + "address": map[string]interface{}{ + "url": sinkURI.String(), + }, + }, + }, + } +} + +func newTransformer() *unstructured.Unstructured { + return &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "testing.cloud.google.com/v1alpha1", + "kind": "Transformer", + "metadata": map[string]interface{}{ + "namespace": testNS, + "name": transformerName, + }, + "status": map[string]interface{}{ + "address": map[string]interface{}{ + "url": transformerURI.String(), + }, + }, + }, + } +} + +func TestAllCases(t *testing.T) { + table := TableTest{{ + Name: "bad workqueue key", + // Make sure Reconcile handles bad keys. + Key: "too/many/parts", + }, { + Name: "key not found", + // Make sure Reconcile handles good keys that don't exist. + Key: "foo/not-found", + }, { + Name: "cannot get sink", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithPullSubscriptionSink(sinkGVK, sinkName), + ), + newSecret(), + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeWarning, "InvalidSink", + `InvalidSink: failed to get ref &ObjectReference{Kind:Sink,Namespace:testnamespace,Name:sink,UID:,APIVersion:testing.cloud.google.com/v1alpha1,ResourceVersion:,FieldPath:,}: sinks.testing.cloud.google.com "sink" not found`), + }, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionStatusObservedGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithPullSubscriptionSink(sinkGVK, sinkName), + // updates + WithInitPullSubscriptionConditions, + WithPullSubscriptionSinkNotFound(), + ), + }}, + }, { + Name: "create client fails", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeWarning, "SubscriptionReconcileFailed", "Failed to reconcile Pub/Sub subscription: client-create-induced-error"), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + CreateClientErr: errors.New("client-create-induced-error"), + }, + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionStatusObservedGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPullSubscriptionTransformerURI(nil), + WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "client-create-induced-error"))), + }}, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + }, { + Name: "topic exists fails", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeWarning, "SubscriptionReconcileFailed", "Failed to reconcile Pub/Sub subscription: topic-exists-induced-error"), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + ExistsErr: errors.New("topic-exists-induced-error"), + }, + }, + }, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionStatusObservedGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPullSubscriptionTransformerURI(nil), + WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "topic-exists-induced-error"))), + }}, + }, { + Name: "topic does not exist", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeWarning, "SubscriptionReconcileFailed", "Failed to reconcile Pub/Sub subscription: Topic %q does not exist", testTopicID), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + Exists: false, + }, + }, + }, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionStatusObservedGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPullSubscriptionTransformerURI(nil), + WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: Topic %q does not exist", failedToReconcileSubscriptionMsg, testTopicID))), + }}, + }, { + Name: "subscription exists fails", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeWarning, "SubscriptionReconcileFailed", "Failed to reconcile Pub/Sub subscription: subscription-exists-induced-error"), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + SubscriptionData: gpubsub.TestSubscriptionData{ + ExistsErr: errors.New("subscription-exists-induced-error"), + }, + }, + }, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionStatusObservedGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPullSubscriptionTransformerURI(nil), + WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "subscription-exists-induced-error"))), + }}, + }, { + Name: "create subscription fails", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeWarning, "SubscriptionReconcileFailed", "Failed to reconcile Pub/Sub subscription: subscription-create-induced-error"), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + Exists: true, + }, + CreateSubscriptionErr: errors.New("subscription-create-induced-error"), + }, + }, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionStatusObservedGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPullSubscriptionTransformerURI(nil), + WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "subscription-create-induced-error"))), + }}, + }, { + Name: "successfully created subscription", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeNormal, "PullSubscriptionReconciled", `PullSubscription reconciled: "%s/%s"`, testNS, sourceName), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + Exists: true, + }, + }, + }, + WantCreates: []runtime.Object{ + newReceiveAdapter(context.Background(), testImage, nil), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPullSubscriptionTransformerURI(nil), + // Updates + WithPullSubscriptionStatusObservedGeneration(generation), + WithPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPullSubscriptionMarkDeployed, + ), + }}, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + }, { + Name: "successful create - reuse existing receive adapter - match", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithPullSubscriptionSink(sinkGVK, sinkName), + ), + newSink(), + newSecret(), + newReceiveAdapter(context.Background(), testImage, nil), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + Exists: true, + }, + }, + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeNormal, "PullSubscriptionReconciled", `PullSubscription reconciled: "%s/%s"`, testNS, sourceName), + }, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPullSubscriptionMarkDeployed, + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPullSubscriptionTransformerURI(nil), + WithPullSubscriptionStatusObservedGeneration(generation), + ), + }}, + }, { + Name: "successful create - reuse existing receive adapter - mismatch", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionTransformer(transformerGVK, transformerName), + ), + newSink(), + newTransformer(), + newSecret(), + newReceiveAdapter(context.Background(), "old"+testImage, nil), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + Exists: true, + }, + }, + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + Eventf(corev1.EventTypeNormal, "PullSubscriptionReconciled", `PullSubscription reconciled: "%s/%s"`, testNS, sourceName), + }, + WantUpdates: []clientgotesting.UpdateActionImpl{{ + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Verb: "update", + Resource: receiveAdapterGVR(), + }, + Object: newReceiveAdapter(context.Background(), testImage, transformerURI), + }}, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, sourceName, resourceGroup), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + //WithPullSubscriptionFinalizers(resourceGroup), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithInitPullSubscriptionConditions, + WithPullSubscriptionProjectID(testProject), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionTransformer(transformerGVK, transformerName), + WithPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPullSubscriptionMarkDeployed, + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionMarkTransformer(transformerURI), + WithPullSubscriptionStatusObservedGeneration(generation), + ), + }}, + }, { + Name: "deleting - failed to delete subscription", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPullSubscriptionMarkDeployed, + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionDeleted, + ), + newSecret(), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + Exists: true, + }, + SubscriptionData: gpubsub.TestSubscriptionData{ + Exists: true, + DeleteErr: errors.New("subscription-delete-induced-error"), + }, + }, + }, + Key: testNS + "/" + sourceName, + WantEvents: []string{ + Eventf(corev1.EventTypeWarning, "SubscriptionDeleteFailed", "Failed to delete Pub/Sub subscription: subscription-delete-induced-error"), + }, + WantStatusUpdates: nil, + }, { + Name: "successfully deleted subscription", + Objects: []runtime.Object{ + NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionStatusObservedGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPullSubscriptionMarkDeployed, + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionDeleted, + ), + newSecret(), + }, + OtherTestData: map[string]interface{}{ + "ps": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + Exists: true, + }, + SubscriptionData: gpubsub.TestSubscriptionData{ + Exists: true, + }, + }, + }, + Key: testNS + "/" + sourceName, + WantEvents: nil, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionObjectMetaGeneration(generation), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + }), + WithPullSubscriptionSink(sinkGVK, sinkName), + WithPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPullSubscriptionSubscriptionID(""), + WithPullSubscriptionMarkDeployed, + WithPullSubscriptionMarkSink(sinkURI), + WithPullSubscriptionStatusObservedGeneration(generation), + WithPullSubscriptionDeleted, + ), + }}, + }} + + defer logtesting.ClearAll() + table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher, testData map[string]interface{}) controller.Reconciler { + ctx = addressable.WithDuck(ctx) + pubsubBase := &pubsub.PubSubBase{ + Base: reconciler.NewBase(ctx, controllerAgentName, cmw), + } + r := &Reconciler{ + Base: &psreconciler.Base{ + PubSubBase: pubsubBase, + DeploymentLister: listers.GetDeploymentLister(), + PullSubscriptionLister: listers.GetPullSubscriptionLister(), + UriResolver: resolver.NewURIResolver(ctx, func(types.NamespacedName) {}), + ReceiveAdapterImage: testImage, + CreateClientFn: gpubsub.TestClientCreator(testData["ps"]), + ControllerAgentName: controllerAgentName, + ResourceGroup: resourceGroup, + }, + } + r.ReconcileDataPlaneFn = r.ReconcileDeployment + return pullsubscription.NewReconciler(ctx, r.Logger, r.RunClientSet, listers.GetPullSubscriptionLister(), r.Recorder, r) + })) +} + +func newReceiveAdapter(ctx context.Context, image string, transformer *apis.URL) runtime.Object { + source := NewPullSubscription(sourceName, testNS, + WithPullSubscriptionUID(sourceUID), + WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &secret, + Project: testProject, + }, + Topic: testTopicID, + })) + args := &resources.ReceiveAdapterArgs{ + Image: image, + Source: source, + Labels: resources.GetLabels(controllerAgentName, sourceName), + SubscriptionID: testSubscriptionID, + SinkURI: sinkURI, + TransformerURI: transformer, + } + return resources.MakeReceiveAdapter(ctx, args) +} + +func receiveAdapterGVR() schema.GroupVersionResource { + return schema.GroupVersionResource{ + Group: "apps", + Version: "v1", + Resource: "deployment", + } +} + +func patchFinalizers(namespace, name, finalizer string, existingFinalizers ...string) clientgotesting.PatchActionImpl { + action := clientgotesting.PatchActionImpl{} + action.Name = name + action.Namespace = namespace + + for i, ef := range existingFinalizers { + existingFinalizers[i] = fmt.Sprintf("%q", ef) + } + if finalizer != "" { + existingFinalizers = append(existingFinalizers, fmt.Sprintf("%q", finalizer)) + } + fname := strings.Join(existingFinalizers, ",") + patch := `{"metadata":{"finalizers":[` + fname + `],"resourceVersion":""}}` + action.Patch = []byte(patch) + return action +} diff --git a/pkg/reconciler/intevents/topic/controller.go b/pkg/reconciler/intevents/topic/controller.go new file mode 100644 index 0000000000..8a2dc5f2e5 --- /dev/null +++ b/pkg/reconciler/intevents/topic/controller.go @@ -0,0 +1,116 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package topic + +import ( + "context" + + "github.com/kelseyhightower/envconfig" + "go.uber.org/zap" + "k8s.io/client-go/tools/cache" + "knative.dev/pkg/configmap" + "knative.dev/pkg/controller" + "knative.dev/pkg/logging" + tracingconfig "knative.dev/pkg/tracing/config" + + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + gpubsub "github.com/google/knative-gcp/pkg/gclient/pubsub" + "github.com/google/knative-gcp/pkg/reconciler" + "github.com/google/knative-gcp/pkg/reconciler/identity" + "github.com/google/knative-gcp/pkg/reconciler/identity/iam" + "github.com/google/knative-gcp/pkg/reconciler/pubsub" + + topicinformer "github.com/google/knative-gcp/pkg/client/injection/informers/intevents/v1alpha1/topic" + topicreconciler "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/topic" + serviceaccountinformers "knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount" + serviceinformer "knative.dev/serving/pkg/client/injection/informers/serving/v1/service" +) + +const ( + // reconcilerName is the name of the reconciler + reconcilerName = "Topics" + + // controllerAgentName is the string used by this controller to identify + // itself when creating events. + controllerAgentName = "cloud-run-events-pubsub-topic-controller" +) + +type envConfig struct { + // Publisher is the image used to publish to Pub/Sub. Required. + Publisher string `envconfig:"PUBSUB_PUBLISHER_IMAGE" required:"true"` +} + +// NewController initializes the controller and is called by the generated code +// Registers event handlers to enqueue events +func NewController( + ctx context.Context, + cmw configmap.Watcher, +) *controller.Impl { + return newControllerWithIAMPolicyManager( + ctx, + cmw, + iam.DefaultIAMPolicyManager()) +} + +func newControllerWithIAMPolicyManager( + ctx context.Context, + cmw configmap.Watcher, + ipm iam.IAMPolicyManager, +) *controller.Impl { + topicInformer := topicinformer.Get(ctx) + serviceInformer := serviceinformer.Get(ctx) + serviceAccountInformer := serviceaccountinformers.Get(ctx) + + logger := logging.FromContext(ctx).Named(controllerAgentName).Desugar() + + var env envConfig + if err := envconfig.Process("", &env); err != nil { + logger.Fatal("Failed to process env var", zap.Error(err)) + } + + pubsubBase := &pubsub.PubSubBase{ + Base: reconciler.NewBase(ctx, controllerAgentName, cmw), + } + + r := &Reconciler{ + PubSubBase: pubsubBase, + Identity: identity.NewIdentity(ctx, ipm), + topicLister: topicInformer.Lister(), + serviceLister: serviceInformer.Lister(), + publisherImage: env.Publisher, + createClientFn: gpubsub.NewClient, + } + + impl := topicreconciler.NewImpl(ctx, r) + + pubsubBase.Logger.Info("Setting up event handlers") + topicInformer.Informer().AddEventHandlerWithResyncPeriod(controller.HandleAll(impl.Enqueue), reconciler.DefaultResyncPeriod) + + serviceInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ + FilterFunc: controller.Filter(v1alpha1.SchemeGroupVersion.WithKind("Topic")), + Handler: controller.HandleAll(impl.EnqueueControllerOf), + }) + + serviceAccountInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ + FilterFunc: controller.FilterGroupVersionKind(v1alpha1.SchemeGroupVersion.WithKind("Topic")), + Handler: controller.HandleAll(impl.EnqueueControllerOf), + }) + + cmw.Watch(tracingconfig.ConfigName, r.UpdateFromTracingConfigMap) + + return impl +} diff --git a/pkg/reconciler/intevents/topic/controller_test.go b/pkg/reconciler/intevents/topic/controller_test.go new file mode 100644 index 0000000000..52243eff0f --- /dev/null +++ b/pkg/reconciler/intevents/topic/controller_test.go @@ -0,0 +1,63 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package topic + +import ( + "os" + "testing" + + iamtesting "github.com/google/knative-gcp/pkg/reconciler/testing" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/system" + tracingconfig "knative.dev/pkg/tracing/config" + + "knative.dev/pkg/configmap" + logtesting "knative.dev/pkg/logging/testing" + . "knative.dev/pkg/reconciler/testing" + + // Fake injection informers + + _ "knative.dev/pkg/client/injection/kube/informers/batch/v1/job/fake" + _ "knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount/fake" + _ "knative.dev/serving/pkg/client/injection/informers/serving/v1/service/fake" + + _ "github.com/google/knative-gcp/pkg/client/injection/informers/intevents/v1alpha1/topic/fake" +) + +func TestNew(t *testing.T) { + defer logtesting.ClearAll() + ctx, _ := SetupFakeContext(t) + + _ = os.Setenv("PUBSUB_PUBLISHER_IMAGE", "PUBSUB_PUBLISHER_IMAGE") + + c := newControllerWithIAMPolicyManager( + ctx, + configmap.NewStaticWatcher( + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: tracingconfig.ConfigName, + Namespace: system.Namespace(), + }, + Data: map[string]string{}, + }), + iamtesting.NoopIAMPolicyManager) + + if c == nil { + t.Fatal("Expected newControllerWithIAMPolicyManager to return a non-nil value") + } +} diff --git a/pkg/reconciler/intevents/topic/doc.go b/pkg/reconciler/intevents/topic/doc.go new file mode 100644 index 0000000000..879f0fed6c --- /dev/null +++ b/pkg/reconciler/intevents/topic/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package topic implements the Pub/Sub Topic controller. +package topic diff --git a/pkg/reconciler/intevents/topic/resources/labels.go b/pkg/reconciler/intevents/topic/resources/labels.go new file mode 100644 index 0000000000..8bf4d3ac2c --- /dev/null +++ b/pkg/reconciler/intevents/topic/resources/labels.go @@ -0,0 +1,32 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + "k8s.io/apimachinery/pkg/labels" +) + +func GetLabelSelector(controller, source string) labels.Selector { + return labels.SelectorFromSet(GetLabels(controller, source)) +} + +func GetLabels(controller, topic string) map[string]string { + return map[string]string{ + "internal.events.google.com/controller": controller, + "internal.events.google.com/topic": topic, + } +} diff --git a/pkg/reconciler/intevents/topic/resources/names.go b/pkg/reconciler/intevents/topic/resources/names.go new file mode 100644 index 0000000000..bfff8b6760 --- /dev/null +++ b/pkg/reconciler/intevents/topic/resources/names.go @@ -0,0 +1,33 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + "fmt" + . "strings" + + "knative.dev/pkg/kmeta" + + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" +) + +func GeneratePublisherName(topic *v1alpha1.Topic) string { + if HasPrefix(topic.Name, "cre-") { + return kmeta.ChildName(topic.Name, "-publish") + } + return kmeta.ChildName(fmt.Sprintf("cre-%s", topic.Name), "-publish") +} diff --git a/pkg/reconciler/intevents/topic/resources/publisher.go b/pkg/reconciler/intevents/topic/resources/publisher.go new file mode 100644 index 0000000000..f0f39b7532 --- /dev/null +++ b/pkg/reconciler/intevents/topic/resources/publisher.go @@ -0,0 +1,139 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + "fmt" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/kmeta" + servingv1 "knative.dev/serving/pkg/apis/serving/v1" + + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + "github.com/google/knative-gcp/pkg/reconciler/identity/resources" +) + +// PublisherArgs are the arguments needed to create a Topic publisher. +// Every field is required. +type PublisherArgs struct { + Image string + Topic *v1alpha1.Topic + Labels map[string]string + + TracingConfig string +} + +const ( + credsVolume = "google-cloud-key" + credsMountPath = "/var/secrets/google" +) + +// DefaultSecretSelector is the default secret selector used to load the creds +// for the publisher to auth with Google Cloud. +func DefaultSecretSelector() *corev1.SecretKeySelector { + return &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "google-cloud-key", + }, + Key: "key.json", + } +} + +func makePublisherPodSpec(args *PublisherArgs) *corev1.PodSpec { + publisherContainer := corev1.Container{ + Image: args.Image, + Env: []corev1.EnvVar{{ + Name: "PROJECT_ID", + Value: args.Topic.Spec.Project, + }, { + Name: "PUBSUB_TOPIC_ID", + Value: args.Topic.Spec.Topic, + }, { + Name: "K_TRACING_CONFIG", + Value: args.TracingConfig, + }}, + } + + // If GCP service account is specified, use that service account as credential. + if args.Topic.Spec.GoogleServiceAccount != "" { + kServiceAccountName := resources.GenerateServiceAccountName(args.Topic.Spec.GoogleServiceAccount) + return &corev1.PodSpec{ + ServiceAccountName: kServiceAccountName, + Containers: []corev1.Container{ + publisherContainer, + }, + } + } + + // Otherwise, use secret as credential. + secret := args.Topic.Spec.Secret + if secret == nil { + secret = DefaultSecretSelector() + } + credsFile := fmt.Sprintf("%s/%s", credsMountPath, secret.Key) + + publisherContainer.Env = append(publisherContainer.Env, corev1.EnvVar{ + Name: "GOOGLE_APPLICATION_CREDENTIALS", + Value: credsFile, + }) + publisherContainer.VolumeMounts = []corev1.VolumeMount{{ + Name: credsVolume, + MountPath: credsMountPath, + }} + + return &corev1.PodSpec{ + Containers: []corev1.Container{ + publisherContainer, + }, + Volumes: []corev1.Volume{{ + Name: credsVolume, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: secret.Name, + }, + }, + }}, + } +} + +// MakePublisher generates (but does not insert into K8s) the Invoker Deployment for +// Channels. +func MakePublisher(args *PublisherArgs) *servingv1.Service { + podSpec := makePublisherPodSpec(args) + + return &servingv1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: args.Topic.Namespace, + Name: GeneratePublisherName(args.Topic), + Labels: args.Labels, + OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(args.Topic)}, + }, + Spec: servingv1.ServiceSpec{ + ConfigurationSpec: servingv1.ConfigurationSpec{ + Template: servingv1.RevisionTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: args.Labels, + }, + Spec: servingv1.RevisionSpec{ + PodSpec: *podSpec, + }, + }, + }, + }, + } +} diff --git a/pkg/reconciler/intevents/topic/resources/publisher_test.go b/pkg/reconciler/intevents/topic/resources/publisher_test.go new file mode 100644 index 0000000000..f23da6cfee --- /dev/null +++ b/pkg/reconciler/intevents/topic/resources/publisher_test.go @@ -0,0 +1,229 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + "encoding/json" + "testing" + + "github.com/google/go-cmp/cmp" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + servingv1 "knative.dev/serving/pkg/apis/serving/v1" + + duckv1alpha1 "github.com/google/knative-gcp/pkg/apis/duck/v1alpha1" + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" +) + +func TestMakePublisher(t *testing.T) { + topic := &v1alpha1.Topic{ + ObjectMeta: metav1.ObjectMeta{ + Name: "topic-name", + Namespace: "topic-namespace", + }, + Spec: v1alpha1.TopicSpec{ + Project: "eventing-name", + Topic: "topic-name", + Secret: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "eventing-secret-name", + }, + Key: "eventing-secret-key", + }, + }, + } + + pub := MakePublisher(&PublisherArgs{ + Image: "test-image", + Topic: topic, + Labels: GetLabels("controller-name", "topic-name"), + TracingConfig: "TracingConfig-ABC123", + }) + + gotb, _ := json.MarshalIndent(pub, "", " ") + got := string(gotb) + + want := `{ + "metadata": { + "name": "cre-topic-name-publish", + "namespace": "topic-namespace", + "creationTimestamp": null, + "labels": { + "internal.events.cloud.google.com/controller": "controller-name", + "internal.events.cloud.google.com/topic": "topic-name" + }, + "ownerReferences": [ + { + "apiVersion": "internal.events.cloud.google.com/v1alpha1", + "kind": "Topic", + "name": "topic-name", + "uid": "", + "controller": true, + "blockOwnerDeletion": true + } + ] + }, + "spec": { + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "internal.events.cloud.google.com/controller": "controller-name", + "internal.events.cloud.google.com/topic": "topic-name" + } + }, + "spec": { + "volumes": [ + { + "name": "google-cloud-key", + "secret": { + "secretName": "eventing-secret-name" + } + } + ], + "containers": [ + { + "name": "", + "image": "test-image", + "env": [ + { + "name": "PROJECT_ID", + "value": "eventing-name" + }, + { + "name": "PUBSUB_TOPIC_ID", + "value": "topic-name" + }, + { + "name": "K_TRACING_CONFIG", + "value": "TracingConfig-ABC123" + }, + { + "name": "GOOGLE_APPLICATION_CREDENTIALS", + "value": "/var/secrets/google/eventing-secret-key" + } + ], + "resources": {}, + "volumeMounts": [ + { + "name": "google-cloud-key", + "mountPath": "/var/secrets/google" + } + ] + } + ] + } + } + }, + "status": {} +}` + + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("unexpected deploy (-want, +got) = %v", diff) + } +} + +func TestMakePublisherWithGCPServiceAccount(t *testing.T) { + gServiceAccountName := "test@test.iam.gserviceaccount.com" + topic := &v1alpha1.Topic{ + ObjectMeta: metav1.ObjectMeta{ + Name: "topic-name", + Namespace: "topic-namespace", + }, + Spec: v1alpha1.TopicSpec{ + Project: "eventing-name", + Topic: "topic-name", + IdentitySpec: duckv1alpha1.IdentitySpec{ + GoogleServiceAccount: gServiceAccountName, + }, + }, + } + + got := MakePublisher(&PublisherArgs{ + Image: "test-image", + Topic: topic, + Labels: GetLabels("controller-name", "topic-name"), + TracingConfig: "TracingConfig-ABC123", + }) + + yes := true + want := &servingv1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cre-topic-name-publish", + Namespace: "topic-namespace", + CreationTimestamp: metav1.Time{}, + Labels: map[string]string{ + "internal.events.cloud.google.com/controller": "controller-name", + "internal.events.cloud.google.com/topic": "topic-name", + }, + OwnerReferences: []metav1.OwnerReference{{ + APIVersion: "internal.events.cloud.google.com/v1alpha1", + Kind: "Topic", + Name: "topic-name", + Controller: &yes, + BlockOwnerDeletion: &yes, + }, + }, + }, + Spec: servingv1.ServiceSpec{ + ConfigurationSpec: servingv1.ConfigurationSpec{ + Template: servingv1.RevisionTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "internal.events.cloud.google.com/controller": "controller-name", + "internal.events.cloud.google.com/topic": "topic-name", + }, + }, + Spec: servingv1.RevisionSpec{ + PodSpec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Name: "", + Image: "test-image", + Env: []corev1.EnvVar{{ + Name: "PROJECT_ID", + Value: "eventing-name", + }, { + Name: "PUBSUB_TOPIC_ID", + Value: "topic-name", + }, { + Name: "K_TRACING_CONFIG", + Value: "TracingConfig-ABC123", + }}, + }}, + ServiceAccountName: "test", + }, + }, + }}, + }, + } + + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("unexpected deploy (-want, +got) = %v", diff) + } +} + +func TestMakePublisherSelector(t *testing.T) { + selector := GetLabelSelector("controller-name", "topic-name") + + want := "internal.events.cloud.google.com/controller=controller-name,internal.events.cloud.google.com/topic=topic-name" + + got := selector.String() + + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("unexpected selector (-want, +got) = %v", diff) + } +} diff --git a/pkg/reconciler/intevents/topic/topic.go b/pkg/reconciler/intevents/topic/topic.go new file mode 100644 index 0000000000..757a7b36f5 --- /dev/null +++ b/pkg/reconciler/intevents/topic/topic.go @@ -0,0 +1,284 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package topic + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/google/knative-gcp/pkg/tracing" + "github.com/google/knative-gcp/pkg/utils" + "go.uber.org/zap" + "google.golang.org/grpc/codes" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + corev1listers "k8s.io/client-go/listers/core/v1" + + "knative.dev/pkg/logging" + "knative.dev/pkg/reconciler" + tracingconfig "knative.dev/pkg/tracing/config" + + servingv1 "knative.dev/serving/pkg/apis/serving/v1" + servinglisters "knative.dev/serving/pkg/client/listers/serving/v1" + + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + topicreconciler "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/topic" + listers "github.com/google/knative-gcp/pkg/client/listers/intevents/v1alpha1" + gpubsub "github.com/google/knative-gcp/pkg/gclient/pubsub" + "github.com/google/knative-gcp/pkg/reconciler/identity" + "github.com/google/knative-gcp/pkg/reconciler/intevents/topic/resources" + "github.com/google/knative-gcp/pkg/reconciler/pubsub" + gstatus "google.golang.org/grpc/status" +) + +const ( + resourceGroup = "topics.internal.events.cloud.google.com" + + deleteTopicFailed = "TopicDeleteFailed" + deleteWorkloadIdentityFailed = "WorkloadIdentityDeleteFailed" + reconciledPublisherFailedReason = "PublisherReconcileFailed" + reconciledSuccessReason = "TopicReconciled" + reconciledTopicFailedReason = "TopicReconcileFailed" + workloadIdentityFailed = "WorkloadIdentityReconcileFailed" +) + +// Reconciler implements controller.Reconciler for Topic resources. +type Reconciler struct { + *pubsub.PubSubBase + // identity reconciler for reconciling workload identity. + *identity.Identity + // topicLister index properties about topics. + topicLister listers.TopicLister + // serviceLister index properties about services. + serviceLister servinglisters.ServiceLister + // serviceAccountLister for reading serviceAccounts. + serviceAccountLister corev1listers.ServiceAccountLister + + publisherImage string + tracingConfig *tracingconfig.Config + + // createClientFn is the function used to create the Pub/Sub client that interacts with Pub/Sub. + // This is needed so that we can inject a mock client for UTs purposes. + createClientFn gpubsub.CreateFn +} + +// Check that our Reconciler implements Interface. +var _ topicreconciler.Interface = (*Reconciler)(nil) + +func (r *Reconciler) ReconcileKind(ctx context.Context, topic *v1alpha1.Topic) reconciler.Event { + ctx = logging.WithLogger(ctx, r.Logger.With(zap.Any("topic", topic))) + + topic.Status.InitializeConditions() + topic.Status.ObservedGeneration = topic.Generation + + // If topic doesn't have ownerReference and GCP ServiceAccount is provided, reconcile workload identity. + // Otherwise, its owner will reconcile workload identity. + if (topic.OwnerReferences == nil || len(topic.OwnerReferences) == 0) && topic.Spec.GoogleServiceAccount != "" { + if _, err := r.Identity.ReconcileWorkloadIdentity(ctx, topic.Spec.Project, topic); err != nil { + return reconciler.NewEvent(corev1.EventTypeWarning, workloadIdentityFailed, "Failed to reconcile Pub/Sub topic workload identity: %s", err.Error()) + } + } + + if err := r.reconcileTopic(ctx, topic); err != nil { + topic.Status.MarkNoTopic(reconciledTopicFailedReason, "Failed to reconcile Pub/Sub topic: %s", err.Error()) + return reconciler.NewEvent(corev1.EventTypeWarning, reconciledTopicFailedReason, "Failed to reconcile Pub/Sub topic: %s", err.Error()) + } + topic.Status.MarkTopicReady() + // Set the topic being used. + topic.Status.TopicID = topic.Spec.Topic + + err, svc := r.reconcilePublisher(ctx, topic) + if err != nil { + topic.Status.MarkPublisherNotDeployed(reconciledPublisherFailedReason, "Failed to reconcile Publisher: %s", err.Error()) + return reconciler.NewEvent(corev1.EventTypeWarning, reconciledPublisherFailedReason, "Failed to reconcile Publisher: %s", err.Error()) + } + + // Update the topic. + topic.Status.PropagatePublisherStatus(&svc.Status) + if svc.Status.IsReady() { + topic.Status.SetAddress(svc.Status.Address.URL) + } + + return reconciler.NewEvent(corev1.EventTypeNormal, reconciledSuccessReason, `Topic reconciled: "%s/%s"`, topic.Namespace, topic.Name) +} + +func (r *Reconciler) reconcileTopic(ctx context.Context, topic *v1alpha1.Topic) error { + if topic.Status.ProjectID == "" { + projectID, err := utils.ProjectID(topic.Spec.Project) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to find project id", zap.Error(err)) + return err + } + // Set the projectID in the status. + topic.Status.ProjectID = projectID + } + + // Auth to GCP is handled by having the GOOGLE_APPLICATION_CREDENTIALS environment variable + // pointing at a credential file. + client, err := r.createClientFn(ctx, topic.Status.ProjectID) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to create Pub/Sub client", zap.Error(err)) + return err + } + defer client.Close() + + t := client.Topic(topic.Spec.Topic) + exists, err := t.Exists(ctx) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to verify Pub/Sub topic exists", zap.Error(err)) + return err + } + + if !exists { + if topic.Spec.PropagationPolicy == v1alpha1.TopicPolicyNoCreateNoDelete { + logging.FromContext(ctx).Desugar().Error("Topic does not exist and the topic policy doesn't allow creation") + return fmt.Errorf("Topic %q does not exist and the topic policy doesn't allow creation", topic.Spec.Topic) + } else { + // Create a new topic with the given name. + t, err = client.CreateTopic(ctx, topic.Spec.Topic) + if err != nil { + // For some reason (maybe some cache invalidation thing), sometimes t.Exists returns that the topic + // doesn't exist but it actually does. When we try to create it again, it fails with an AlreadyExists + // reason. We check for that error here. If it happens, then return nil. + if st, ok := gstatus.FromError(err); !ok { + logging.FromContext(ctx).Desugar().Error("Failed from Pub/Sub client while creating topic", zap.Error(err)) + return err + } else if st.Code() != codes.AlreadyExists { + logging.FromContext(ctx).Desugar().Error("Failed to create Pub/Sub topic", zap.Error(err)) + return err + } + return nil + } + } + } + return nil +} + +// deleteTopic looks at the status.TopicID and if non-empty, +// hence indicating that we have created a topic successfully, +// remove it. +func (r *Reconciler) deleteTopic(ctx context.Context, topic *v1alpha1.Topic) error { + if topic.Status.TopicID == "" { + return nil + } + + // At this point the project ID should have been populated in the status. + // Querying Pub/Sub as the topic could have been deleted outside the cluster (e.g, through gcloud). + client, err := r.createClientFn(ctx, topic.Status.ProjectID) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to create Pub/Sub client", zap.Error(err)) + return err + } + defer client.Close() + + t := client.Topic(topic.Status.TopicID) + exists, err := t.Exists(ctx) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to verify Pub/Sub topic exists", zap.Error(err)) + return err + } + if exists { + // Delete the topic. + if err := t.Delete(ctx); err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to delete Pub/Sub topic", zap.Error(err)) + return err + } + } + return nil +} + +func (r *Reconciler) reconcilePublisher(ctx context.Context, topic *v1alpha1.Topic) (error, *servingv1.Service) { + name := resources.GeneratePublisherName(topic) + existing, err := r.serviceLister.Services(topic.Namespace).Get(name) + if err != nil { + if !apierrors.IsNotFound(err) { + logging.FromContext(ctx).Desugar().Error("Unable to get an existing publisher", zap.Error(err)) + return err, nil + } + existing = nil + } else if !metav1.IsControlledBy(existing, topic) { + p, _ := json.Marshal(existing) + logging.FromContext(ctx).Desugar().Error("Topic does not own publisher service", zap.Any("publisher", p)) + return fmt.Errorf("Topic %q does not own publisher service: %q", topic.Name, name), nil + } + + tracingCfg, err := tracing.ConfigToJSON(r.tracingConfig) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Error serializing tracing config", zap.Error(err)) + } + + desired := resources.MakePublisher(&resources.PublisherArgs{ + Image: r.publisherImage, + Topic: topic, + Labels: resources.GetLabels(controllerAgentName, topic.Name), + TracingConfig: tracingCfg, + }) + + svc := existing + if existing == nil { + svc, err = r.ServingClientSet.ServingV1().Services(topic.Namespace).Create(desired) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to create publisher", zap.Error(err)) + return err, nil + } + } else if !equality.Semantic.DeepEqual(&existing.Spec, &desired.Spec) { + existing.Spec = desired.Spec + svc, err = r.ServingClientSet.ServingV1().Services(topic.Namespace).Update(existing) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to update publisher", zap.Any("publisher", existing), zap.Error(err)) + return err, nil + } + } + return nil, svc +} + +func (r *Reconciler) UpdateFromTracingConfigMap(cfg *corev1.ConfigMap) { + if cfg == nil { + r.Logger.Error("Tracing ConfigMap is nil") + return + } + delete(cfg.Data, "_example") + + tracingCfg, err := tracingconfig.NewTracingConfigFromConfigMap(cfg) + if err != nil { + r.Logger.Warnw("failed to create tracing config from configmap", zap.String("cfg.Name", cfg.Name)) + return + } + r.tracingConfig = tracingCfg + r.Logger.Debugw("Updated Tracing config", zap.Any("tracingCfg", r.tracingConfig)) + // TODO: requeue all Topics. See https://github.com/google/knative-gcp/issues/457. +} + +func (r *Reconciler) FinalizeKind(ctx context.Context, topic *v1alpha1.Topic) reconciler.Event { + // If topic doesn't have ownerReference, k8s ServiceAccount exists and it only has one ownerReference, remove the corresponding GCP ServiceAccount iam policy binding. + // No need to delete k8s ServiceAccount, it will be automatically handled by k8s Garbage Collection. + if (topic.OwnerReferences == nil || len(topic.OwnerReferences) == 0) && topic.Spec.GoogleServiceAccount != "" { + if err := r.Identity.DeleteWorkloadIdentity(ctx, topic.Spec.Project, topic); err != nil { + return reconciler.NewEvent(corev1.EventTypeWarning, deleteWorkloadIdentityFailed, "Failed to delete delete Pub/Sub topic workload identity: %s", err.Error()) + } + } + if topic.Spec.PropagationPolicy == v1alpha1.TopicPolicyCreateDelete { + logging.FromContext(ctx).Desugar().Debug("Deleting Pub/Sub topic") + if err := r.deleteTopic(ctx, topic); err != nil { + return reconciler.NewEvent(corev1.EventTypeWarning, deleteTopicFailed, "Failed to delete Pub/Sub topic: %s", err.Error()) + } + } + return nil +} diff --git a/pkg/reconciler/intevents/topic/topic_test.go b/pkg/reconciler/intevents/topic/topic_test.go new file mode 100644 index 0000000000..bdc62376e5 --- /dev/null +++ b/pkg/reconciler/intevents/topic/topic_test.go @@ -0,0 +1,705 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Veroute.on 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package topic + +import ( + "context" + "errors" + "fmt" + "strings" + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/client-go/kubernetes/scheme" + clientgotesting "k8s.io/client-go/testing" + + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" + "knative.dev/pkg/configmap" + "knative.dev/pkg/controller" + logtesting "knative.dev/pkg/logging/testing" + . "knative.dev/pkg/reconciler/testing" + servingv1 "knative.dev/serving/pkg/apis/serving/v1" + + pubsubv1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/topic" + gpubsub "github.com/google/knative-gcp/pkg/gclient/pubsub/testing" + "github.com/google/knative-gcp/pkg/reconciler" + "github.com/google/knative-gcp/pkg/reconciler/intevents/topic/resources" + "github.com/google/knative-gcp/pkg/reconciler/pubsub" + . "github.com/google/knative-gcp/pkg/reconciler/testing" +) + +const ( + topicName = "hubbub" + sinkName = "sink" + + testNS = "testnamespace" + testImage = "test_image" + topicUID = topicName + "-abc-123" + testProject = "test-project-id" + testTopicID = "cloud-run-topic-" + testNS + "-" + topicName + "-" + topicUID + testTopicURI = "http://" + topicName + "-topic." + testNS + ".svc.cluster.local" + + secretName = "testing-secret" + + failedToReconcileTopicMsg = `Failed to reconcile Pub/Sub topic` + failedToDeleteTopicMsg = `Failed to delete Pub/Sub topic` +) + +var ( + trueVal = true + + sinkDNS = sinkName + ".mynamespace.svc.cluster.local" + sinkURI = "http://" + sinkDNS + "/" + + sinkGVK = metav1.GroupVersionKind{ + Group: "testing.cloud.google.com", + Version: "v1alpha1", + Kind: "Sink", + } + + secret = corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: secretName, + }, + Key: "testing-key", + } +) + +func init() { + // Add types to scheme + _ = pubsubv1alpha1.AddToScheme(scheme.Scheme) +} + +func newSink() *unstructured.Unstructured { + return &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "testing.cloud.google.com/v1alpha1", + "kind": "Sink", + "metadata": map[string]interface{}{ + "namespace": testNS, + "name": sinkName, + }, + "status": map[string]interface{}{ + "address": map[string]interface{}{ + "hostname": sinkDNS, + }, + }, + }, + } +} + +func newSecret() *corev1.Secret { + return &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: testNS, + Name: secretName, + }, + Data: map[string][]byte{ + "testing-key": []byte("abcd"), + }, + } +} + +func TestAllCases(t *testing.T) { + table := TableTest{{ + Name: "bad workqueue key", + // Make sure Reconcile handles bad keys. + Key: "too/many/parts", + }, { + Name: "key not found", + // Make sure Reconcile handles good keys that don't exist. + Key: "foo/not-found", + }, { + Name: "create client fails", + Objects: []runtime.Object{ + NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("NoCreateNoDelete"), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + topicName, + OtherTestData: map[string]interface{}{ + "topic": gpubsub.TestClientData{ + CreateClientErr: errors.New("create-client-induced-error"), + }, + }, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", topicName), + Eventf(corev1.EventTypeWarning, reconciledTopicFailedReason, "Failed to reconcile Pub/Sub topic: create-client-induced-error"), + }, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, topicName, resourceGroup), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicProjectID(testProject), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("NoCreateNoDelete"), + // Updates + WithInitTopicConditions, + WithTopicNoTopic("TopicReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileTopicMsg, "create-client-induced-error"))), + }}, + }, { + Name: "verify topic exists fails", + Objects: []runtime.Object{ + NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("NoCreateNoDelete"), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + topicName, + OtherTestData: map[string]interface{}{ + "topic": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + ExistsErr: errors.New("topic-exists-induced-error"), + }, + }, + }, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", topicName), + Eventf(corev1.EventTypeWarning, reconciledTopicFailedReason, "Failed to reconcile Pub/Sub topic: topic-exists-induced-error"), + }, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, topicName, resourceGroup), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicProjectID(testProject), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("NoCreateNoDelete"), + // Updates + WithInitTopicConditions, + WithTopicNoTopic("TopicReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileTopicMsg, "topic-exists-induced-error"))), + }}, + }, { + Name: "topic does not exist and propagation policy is NoCreateNoDelete", + Objects: []runtime.Object{ + NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("NoCreateNoDelete"), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + topicName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", topicName), + Eventf(corev1.EventTypeWarning, reconciledTopicFailedReason, "Failed to reconcile Pub/Sub topic: Topic %q does not exist and the topic policy doesn't allow creation", testTopicID), + }, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, topicName, resourceGroup), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicProjectID(testProject), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("NoCreateNoDelete"), + // Updates + WithInitTopicConditions, + WithTopicNoTopic("TopicReconcileFailed", fmt.Sprintf("%s: Topic %q does not exist and the topic policy doesn't allow creation", failedToReconcileTopicMsg, testTopicID))), + }}, + }, { + Name: "create topic fails", + Objects: []runtime.Object{ + NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("CreateNoDelete"), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + topicName, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", topicName), + Eventf(corev1.EventTypeWarning, reconciledTopicFailedReason, "Failed to reconcile Pub/Sub topic: create-topic-induced-error"), + }, + OtherTestData: map[string]interface{}{ + "topic": gpubsub.TestClientData{ + CreateTopicErr: errors.New("create-topic-induced-error"), + }, + }, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, topicName, resourceGroup), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicProjectID(testProject), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("CreateNoDelete"), + // Updates + WithInitTopicConditions, + WithTopicNoTopic("TopicReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileTopicMsg, "create-topic-induced-error"))), + }}, + }, { + Name: "publisher has not yet been reconciled", + Objects: []runtime.Object{ + NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("CreateNoDelete"), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + topicName, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, topicName, resourceGroup), + }, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", topicName), + Eventf(corev1.EventTypeNormal, reconciledSuccessReason, `Topic reconciled: "%s/%s"`, testNS, topicName), + }, + WantCreates: []runtime.Object{ + newPublisher(), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicProjectID(testProject), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("CreateNoDelete"), + // Updates + WithInitTopicConditions, + WithTopicReady(testTopicID), + WithTopicPublisherNotConfigured()), + }}, + }, + { + Name: "the status of publisher is false", + Objects: []runtime.Object{ + NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("CreateNoDelete"), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + topicName, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, topicName, resourceGroup), + }, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", topicName), + Eventf(corev1.EventTypeNormal, reconciledSuccessReason, `Topic reconciled: "%s/%s"`, testNS, topicName), + }, + WithReactors: []clientgotesting.ReactionFunc{ + ProvideResource("create", "services", makeFalseStatusPublisher("PublisherNotDeployed", "PublisherNotDeployed")), + }, + WantCreates: []runtime.Object{ + newPublisher(), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicProjectID(testProject), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("CreateNoDelete"), + // Updates + WithInitTopicConditions, + WithTopicReady(testTopicID), + WithTopicPublisherNotDeployed("PublisherNotDeployed", "PublisherNotDeployed")), + }}, + }, { + Name: "the status of publisher is unknown", + Objects: []runtime.Object{ + NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("CreateNoDelete"), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + topicName, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, topicName, resourceGroup), + }, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", topicName), + Eventf(corev1.EventTypeNormal, reconciledSuccessReason, `Topic reconciled: "%s/%s"`, testNS, topicName), + }, + WithReactors: []clientgotesting.ReactionFunc{ + ProvideResource("create", "services", makeUnknownStatusPublisher("PublisherUnknown", "PublisherUnknown")), + }, + WantCreates: []runtime.Object{ + newPublisher(), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicProjectID(testProject), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("CreateNoDelete"), + // Updates + WithInitTopicConditions, + WithTopicReady(testTopicID), + WithTopicPublisherUnknown("PublisherUnknown", "PublisherUnknown")), + }}, + }, { + Name: "topic successfully reconciles and is ready", + Objects: []runtime.Object{ + NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("CreateNoDelete"), + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + topicName, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, topicName, resourceGroup), + }, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", topicName), + Eventf(corev1.EventTypeNormal, reconciledSuccessReason, `Topic reconciled: "%s/%s"`, testNS, topicName), + }, + WithReactors: []clientgotesting.ReactionFunc{ + ProvideResource("create", "services", makeReadyPublisher()), + }, + WantCreates: []runtime.Object{ + newPublisher(), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicProjectID(testProject), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("CreateNoDelete"), + // Updates + WithInitTopicConditions, + WithTopicReady(testTopicID), + WithTopicPublisherDeployed, + WithTopicAddress(testTopicURI)), + }}, + }, { + Name: "topic successfully reconciles and reuses existing publisher", + Objects: []runtime.Object{ + NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("CreateNoDelete"), + ), + newSink(), + newSecret(), + makeReadyPublisher(), + NewService(topicName+"-topic", testNS, + WithServiceOwnerReferences(ownerReferences()), + WithServiceLabels(resources.GetLabels(controllerAgentName, topicName)), + WithServicePorts(servicePorts())), + }, + Key: testNS + "/" + topicName, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(testNS, topicName, resourceGroup), + }, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", topicName), + Eventf(corev1.EventTypeNormal, reconciledSuccessReason, `Topic reconciled: "%s/%s"`, testNS, topicName), + }, + WithReactors: []clientgotesting.ReactionFunc{}, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicProjectID(testProject), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("CreateNoDelete"), + // Updates + WithInitTopicConditions, + WithTopicReady(testTopicID), + WithTopicPublisherDeployed, + WithTopicAddress(testTopicURI)), + }}, + }, { + Name: "delete topic - policy CreateNoDelete", + Objects: []runtime.Object{ + NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("CreateNoDelete"), + WithTopicDeleted, + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + topicName, + WantEvents: nil, + WantStatusUpdates: nil, + }, { + Name: "delete topic - policy CreateDelete", + Objects: []runtime.Object{ + NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("CreateDelete"), + WithTopicTopicID(topicName), + WithTopicDeleted, + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + topicName, + WantEvents: nil, + WantStatusUpdates: nil, + }, { + Name: "fail to delete - policy CreateDelete", + Objects: []runtime.Object{ + NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + }), + WithTopicPropagationPolicy("CreateDelete"), + WithTopicTopicID(topicName), + WithTopicDeleted, + ), + newSink(), + newSecret(), + }, + Key: testNS + "/" + topicName, + WantEvents: []string{ + Eventf(corev1.EventTypeWarning, deleteTopicFailed, "Failed to delete Pub/Sub topic: delete-topic-induced-error"), + }, + OtherTestData: map[string]interface{}{ + "topic": gpubsub.TestClientData{ + TopicData: gpubsub.TestTopicData{ + Exists: true, + DeleteErr: errors.New("delete-topic-induced-error"), + }, + }, + }, + WantStatusUpdates: nil, + }} + + defer logtesting.ClearAll() + table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher, testData map[string]interface{}) controller.Reconciler { + pubsubBase := &pubsub.PubSubBase{ + Base: reconciler.NewBase(ctx, controllerAgentName, cmw), + } + r := &Reconciler{ + PubSubBase: pubsubBase, + topicLister: listers.GetTopicLister(), + serviceLister: listers.GetV1ServiceLister(), + publisherImage: testImage, + createClientFn: gpubsub.TestClientCreator(testData["topic"]), + } + return topic.NewReconciler(ctx, r.Logger, r.RunClientSet, listers.GetTopicLister(), r.Recorder, r) + })) + +} + +func ProvideResource(verb, resource string, obj runtime.Object) clientgotesting.ReactionFunc { + return func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) { + if !action.Matches(verb, resource) { + return false, nil, nil + } + return true, obj, nil + } +} + +func patchFinalizers(namespace, name, finalizer string, existingFinalizers ...string) clientgotesting.PatchActionImpl { + action := clientgotesting.PatchActionImpl{} + action.Name = name + action.Namespace = namespace + + for i, ef := range existingFinalizers { + existingFinalizers[i] = fmt.Sprintf("%q", ef) + } + if finalizer != "" { + existingFinalizers = append(existingFinalizers, fmt.Sprintf("%q", finalizer)) + } + fname := strings.Join(existingFinalizers, ",") + patch := `{"metadata":{"finalizers":[` + fname + `],"resourceVersion":""}}` + action.Patch = []byte(patch) + return action +} + +func ownerReferences() []metav1.OwnerReference { + return []metav1.OwnerReference{{ + APIVersion: "internal.events.cloud.google.com/v1alpha1", + Kind: "Topic", + Name: topicName, + UID: topicUID, + Controller: &trueVal, + BlockOwnerDeletion: &trueVal, + }} +} + +func servicePorts() []corev1.ServicePort { + svcPorts := []corev1.ServicePort{ + { + Name: "http", + Port: 80, + TargetPort: intstr.FromInt(8080), + }, { + Name: "metrics", + Port: 9090, + }, + } + return svcPorts +} + +func makeReadyPublisher() *servingv1.Service { + pub := newPublisher() + pub.Status.Conditions = []apis.Condition{{ + Type: apis.ConditionReady, + Status: "True", + }} + uri, _ := apis.ParseURL(testTopicURI) + pub.Status.Address = &duckv1.Addressable{ + URL: uri, + } + return pub +} + +func makeUnknownStatusPublisher(reason, message string) *servingv1.Service { + pub := newPublisher() + pub.Status.Conditions = []apis.Condition{{ + Type: apis.ConditionReady, + Status: "Unknown", + Reason: reason, + Message: message, + }} + return pub +} + +func makeFalseStatusPublisher(reason, message string) *servingv1.Service { + pub := newPublisher() + pub.Status.Conditions = []apis.Condition{{ + Type: apis.ConditionReady, + Status: "False", + Reason: reason, + Message: message, + }} + return pub +} + +func newPublisher() *servingv1.Service { + topic := NewTopic(topicName, testNS, + WithTopicUID(topicUID), + WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Project: testProject, + Topic: testTopicID, + Secret: &secret, + })) + args := &resources.PublisherArgs{ + Image: testImage, + Topic: topic, + Labels: resources.GetLabels(controllerAgentName, topicName), + } + return resources.MakePublisher(args) +} From b3303828fe6761bf2620dab41c3c4730fddd8e0c Mon Sep 17 00:00:00 2001 From: Adam Harwayne Date: Fri, 1 May 2020 17:05:37 -0700 Subject: [PATCH 2/7] Prefix PullSubscription and Topic functions with PubSub. This is being done because the intevents version will soon need the same functions and will be given the non-prefixed names (as they will continue to exist past the next release). --- .../events/auditlogs/auditlogs_test.go | 228 +++++----- pkg/reconciler/events/build/build_test.go | 26 +- pkg/reconciler/events/pubsub/pubsub_test.go | 28 +- .../events/scheduler/scheduler_test.go | 204 ++++----- pkg/reconciler/events/storage/storage_test.go | 180 ++++---- .../keda/pullsubscription_test.go | 414 +++++++++--------- .../keda/resources/scaled_object_test.go | 8 +- .../static/pullsubscription_test.go | 392 ++++++++--------- pkg/reconciler/pubsub/reconciler_test.go | 348 +++++++-------- pkg/reconciler/pubsub/topic/topic_test.go | 252 +++++------ ...cription.go => pubsub_pullsubscription.go} | 101 ++--- .../testing/{topic.go => pubsub_topic.go} | 66 +-- test/e2e/test_pullsubscription.go | 12 +- 13 files changed, 1103 insertions(+), 1156 deletions(-) rename pkg/reconciler/testing/{pullsubscription.go => pubsub_pullsubscription.go} (54%) rename pkg/reconciler/testing/{topic.go => pubsub_topic.go} (59%) diff --git a/pkg/reconciler/events/auditlogs/auditlogs_test.go b/pkg/reconciler/events/auditlogs/auditlogs_test.go index 2a5f0e0898..dc086c9d60 100644 --- a/pkg/reconciler/events/auditlogs/auditlogs_test.go +++ b/pkg/reconciler/events/auditlogs/auditlogs_test.go @@ -155,16 +155,16 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceTopicUnknown("TopicNotConfigured", failedToReconcileTopicMsg)), }}, WantCreates: []runtime.Object{ - NewTopic(sourceName, testNS, - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Topic: "cloudauditlogssource-" + sourceUID, PropagationPolicy: "CreateDelete", }), - WithTopicLabels(map[string]string{ + WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": sourceName, }), - WithTopicOwnerReferences([]metav1.OwnerReference{sourceOwnerRef(sourceName, sourceUID)}), + WithPubSubTopicOwnerReferences([]metav1.OwnerReference{sourceOwnerRef(sourceName, sourceUID)}), ), }, WantPatches: []clientgotesting.PatchActionImpl{ @@ -182,8 +182,8 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceMethodName(testMethodName), WithCloudAuditLogsSourceServiceName(testServiceName), ), - NewTopic(sourceName, testNS, - WithTopicTopicID(testTopicID), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicTopicID(testTopicID), ), }, Key: testNS + "/" + sourceName, @@ -209,9 +209,9 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceMethodName(testMethodName), WithCloudAuditLogsSourceServiceName(testServiceName), ), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), ), }, Key: testNS + "/" + sourceName, @@ -239,10 +239,10 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceMethodName(testMethodName), WithCloudAuditLogsSourceServiceName(testServiceName), ), - NewTopic(sourceName, testNS, - WithTopicReady(""), - WithTopicProjectID(testProject), - WithTopicAddress(testTopicURI), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(""), + WithPubSubTopicProjectID(testProject), + WithPubSubTopicAddress(testTopicURI), ), }, Key: testNS + "/" + sourceName, @@ -270,10 +270,10 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceMethodName(testMethodName), WithCloudAuditLogsSourceServiceName(testServiceName), ), - NewTopic(sourceName, testNS, - WithTopicReady("garbaaaaage"), - WithTopicProjectID(testProject), - WithTopicAddress(testTopicURI), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady("garbaaaaage"), + WithPubSubTopicProjectID(testProject), + WithPubSubTopicAddress(testTopicURI), ), }, Key: testNS + "/" + sourceName, @@ -301,9 +301,9 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceMethodName(testMethodName), WithCloudAuditLogsSourceServiceName(testServiceName), ), - NewTopic(sourceName, testNS, - WithTopicFailed(), - WithTopicTopicID(testTopicID), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicFailed(), + WithPubSubTopicTopicID(testTopicID), ), }, Key: testNS + "/" + sourceName, @@ -330,9 +330,9 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceMethodName(testMethodName), WithCloudAuditLogsSourceServiceName(testServiceName), ), - NewTopic(sourceName, testNS, - WithTopicUnknown(), - WithTopicTopicID(testTopicID), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicUnknown(), + WithPubSubTopicTopicID(testTopicID), ), }, Key: testNS + "/" + sourceName, @@ -359,10 +359,10 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceServiceName(testServiceName), WithCloudAuditLogsSourceSink(sinkGVK, sinkName), ), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), }, Key: testNS + "/" + sourceName, @@ -378,23 +378,23 @@ func TestAllCases(t *testing.T) { ), }}, WantCreates: []runtime.Object{ - NewPullSubscriptionWithNoDefaults(sourceName, testNS, - WithPullSubscriptionSpecWithNoDefaults(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscriptionWithNoDefaults(sourceName, testNS, + WithPubSubPullSubscriptionSpecWithNoDefaults(pubsubv1alpha1.PullSubscriptionSpec{ Topic: testTopicID, PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, }, AdapterType: converters.CloudAuditLogsConverter, }), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionLabels(map[string]string{ + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": sourceName, }), - WithPullSubscriptionAnnotations(map[string]string{ + WithPubSubPullSubscriptionAnnotations(map[string]string{ "metrics-resource-group": resourceGroup, }), - WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{sourceOwnerRef(sourceName, sourceUID)}), + WithPubSubPullSubscriptionOwnerReferences([]metav1.OwnerReference{sourceOwnerRef(sourceName, sourceUID)}), ), }, WantPatches: []clientgotesting.PatchActionImpl{ @@ -412,12 +412,12 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceServiceName(testServiceName), WithCloudAuditLogsSourceSink(sinkGVK, sinkName), ), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(sourceName, testNS), + NewPubSubPullSubscriptionWithNoDefaults(sourceName, testNS), }, Key: testNS + "/" + sourceName, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ @@ -446,12 +446,12 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceServiceName(testServiceName), WithCloudAuditLogsSourceSink(sinkGVK, sinkName), ), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(sourceName, testNS, WithPullSubscriptionFailed()), + NewPubSubPullSubscriptionWithNoDefaults(sourceName, testNS, WithPubSubPullSubscriptionFailed()), }, Key: testNS + "/" + sourceName, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ @@ -480,12 +480,12 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceServiceName(testServiceName), WithCloudAuditLogsSourceSink(sinkGVK, sinkName), ), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(sourceName, testNS, WithPullSubscriptionUnknown()), + NewPubSubPullSubscriptionWithNoDefaults(sourceName, testNS, WithPubSubPullSubscriptionUnknown()), }, Key: testNS + "/" + sourceName, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ @@ -514,13 +514,13 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceServiceName(testServiceName), WithCloudAuditLogsSourceSink(sinkGVK, sinkName), ), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(sourceName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(sourceName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), }, Key: testNS + "/" + sourceName, @@ -557,13 +557,13 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceServiceName(testServiceName), WithCloudAuditLogsSourceSink(sinkGVK, sinkName), ), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(sourceName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(sourceName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), }, Key: testNS + "/" + sourceName, @@ -600,13 +600,13 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceServiceName(testServiceName), WithCloudAuditLogsSourceSink(sinkGVK, sinkName), ), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(sourceName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(sourceName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), }, Key: testNS + "/" + sourceName, @@ -643,13 +643,13 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceServiceName(testServiceName), WithCloudAuditLogsSourceSink(sinkGVK, sinkName), ), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(sourceName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(sourceName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), }, Key: testNS + "/" + sourceName, @@ -687,13 +687,13 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceSink(sinkGVK, sinkName), WithCloudAuditLogsSourceServiceName(testServiceName), WithCloudAuditLogsSourceMethodName(testMethodName)), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(sourceName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(sourceName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), }, Key: testNS + "/" + sourceName, @@ -741,13 +741,13 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceSink(sinkGVK, sinkName), WithCloudAuditLogsSourceServiceName(testServiceName), WithCloudAuditLogsSourceMethodName(testMethodName)), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(sourceName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(sourceName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), }, Key: testNS + "/" + sourceName, @@ -795,13 +795,13 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceSink(sinkGVK, sinkName), WithCloudAuditLogsSourceServiceName(testServiceName), WithCloudAuditLogsSourceMethodName(testMethodName)), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(sourceName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(sourceName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), }, Key: testNS + "/" + sourceName, @@ -844,13 +844,13 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceServiceName(testServiceName), WithCloudAuditLogsSourceSink(sinkGVK, sinkName), ), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(sourceName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(sourceName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), }, Key: testNS + "/" + sourceName, @@ -904,13 +904,13 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceSinkID(testSinkID), WithCloudAuditLogsSourceDeletionTimestamp, ), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(sourceName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(sourceName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), }, Key: testNS + "/" + sourceName, @@ -950,13 +950,13 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceSinkID(testSinkID), WithCloudAuditLogsSourceDeletionTimestamp, ), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(sourceName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(sourceName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), }, Key: testNS + "/" + sourceName, @@ -1008,13 +1008,13 @@ func TestAllCases(t *testing.T) { WithCloudAuditLogsSourceSinkID(testSinkID), WithCloudAuditLogsSourceDeletionTimestamp, ), - NewTopic(sourceName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(sourceName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(sourceName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(sourceName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), }, Key: testNS + "/" + sourceName, diff --git a/pkg/reconciler/events/build/build_test.go b/pkg/reconciler/events/build/build_test.go index 1ff488d2be..851f6ff6b3 100644 --- a/pkg/reconciler/events/build/build_test.go +++ b/pkg/reconciler/events/build/build_test.go @@ -166,22 +166,22 @@ func TestAllCases(t *testing.T) { ), }}, WantCreates: []runtime.Object{ - NewPullSubscriptionWithNoDefaults(buildName, testNS, - WithPullSubscriptionSpecWithNoDefaults(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscriptionWithNoDefaults(buildName, testNS, + WithPubSubPullSubscriptionSpecWithNoDefaults(pubsubv1alpha1.PullSubscriptionSpec{ Topic: testTopicID, PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, }, }), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionLabels(map[string]string{ + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": buildName, }), - WithPullSubscriptionAnnotations(map[string]string{ + WithPubSubPullSubscriptionAnnotations(map[string]string{ "metrics-resource-group": resourceGroup, }), - WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + WithPubSubPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), }, WantPatches: []clientgotesting.PatchActionImpl{ @@ -199,8 +199,8 @@ func TestAllCases(t *testing.T) { WithCloudBuildSourceTopic(testTopicID), WithCloudBuildSourceSink(sinkGVK, sinkName), ), - NewPullSubscriptionWithNoDefaults(buildName, testNS, - WithPullSubscriptionReadyStatus(corev1.ConditionFalse, "PullSubscriptionFalse", "status false test message")), + NewPubSubPullSubscriptionWithNoDefaults(buildName, testNS, + WithPubSubPullSubscriptionReadyStatus(corev1.ConditionFalse, "PullSubscriptionFalse", "status false test message")), newSink(), }, Key: testNS + "/" + buildName, @@ -230,8 +230,8 @@ func TestAllCases(t *testing.T) { WithCloudBuildSourceTopic(testTopicID), WithCloudBuildSourceSink(sinkGVK, sinkName), ), - NewPullSubscriptionWithNoDefaults(buildName, testNS, - WithPullSubscriptionReadyStatus(corev1.ConditionUnknown, "PullSubscriptionUnknown", "status unknown test message")), + NewPubSubPullSubscriptionWithNoDefaults(buildName, testNS, + WithPubSubPullSubscriptionReadyStatus(corev1.ConditionUnknown, "PullSubscriptionUnknown", "status unknown test message")), newSink(), }, Key: testNS + "/" + buildName, @@ -261,9 +261,9 @@ func TestAllCases(t *testing.T) { WithCloudBuildSourceTopic(testTopicID), WithCloudBuildSourceSink(sinkGVK, sinkName), ), - NewPullSubscriptionWithNoDefaults(buildName, testNS, - WithPullSubscriptionReady(sinkURI), - WithPullSubscriptionReadyStatus(corev1.ConditionTrue, "PullSubscriptionNoReady", ""), + NewPubSubPullSubscriptionWithNoDefaults(buildName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), + WithPubSubPullSubscriptionReadyStatus(corev1.ConditionTrue, "PullSubscriptionNoReady", ""), ), newSink(), }, diff --git a/pkg/reconciler/events/pubsub/pubsub_test.go b/pkg/reconciler/events/pubsub/pubsub_test.go index f8fbf6c2e1..cc937d47b6 100644 --- a/pkg/reconciler/events/pubsub/pubsub_test.go +++ b/pkg/reconciler/events/pubsub/pubsub_test.go @@ -164,23 +164,23 @@ func TestAllCases(t *testing.T) { ), }}, WantCreates: []runtime.Object{ - NewPullSubscriptionWithNoDefaults(pubsubName, testNS, - WithPullSubscriptionSpecWithNoDefaults(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscriptionWithNoDefaults(pubsubName, testNS, + WithPubSubPullSubscriptionSpecWithNoDefaults(pubsubv1alpha1.PullSubscriptionSpec{ Topic: testTopicID, PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, }, }), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMode(pubsubv1alpha1.ModePushCompatible), - WithPullSubscriptionLabels(map[string]string{ + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMode(pubsubv1alpha1.ModePushCompatible), + WithPubSubPullSubscriptionLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": pubsubName, }), - WithPullSubscriptionAnnotations(map[string]string{ + WithPubSubPullSubscriptionAnnotations(map[string]string{ "metrics-resource-group": resourceGroup, }), - WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + WithPubSubPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), }, WantPatches: []clientgotesting.PatchActionImpl{ @@ -198,8 +198,8 @@ func TestAllCases(t *testing.T) { WithCloudPubSubSourceTopic(testTopicID), WithCloudPubSubSourceSink(sinkGVK, sinkName), ), - NewPullSubscriptionWithNoDefaults(pubsubName, testNS, - WithPullSubscriptionReadyStatus(corev1.ConditionFalse, "PullSubscriptionFalse", "status false test message")), + NewPubSubPullSubscriptionWithNoDefaults(pubsubName, testNS, + WithPubSubPullSubscriptionReadyStatus(corev1.ConditionFalse, "PullSubscriptionFalse", "status false test message")), newSink(), }, Key: testNS + "/" + pubsubName, @@ -229,8 +229,8 @@ func TestAllCases(t *testing.T) { WithCloudPubSubSourceTopic(testTopicID), WithCloudPubSubSourceSink(sinkGVK, sinkName), ), - NewPullSubscriptionWithNoDefaults(pubsubName, testNS, - WithPullSubscriptionReadyStatus(corev1.ConditionUnknown, "PullSubscriptionUnknown", "status unknown test message")), + NewPubSubPullSubscriptionWithNoDefaults(pubsubName, testNS, + WithPubSubPullSubscriptionReadyStatus(corev1.ConditionUnknown, "PullSubscriptionUnknown", "status unknown test message")), newSink(), }, Key: testNS + "/" + pubsubName, @@ -260,9 +260,9 @@ func TestAllCases(t *testing.T) { WithCloudPubSubSourceTopic(testTopicID), WithCloudPubSubSourceSink(sinkGVK, sinkName), ), - NewPullSubscriptionWithNoDefaults(pubsubName, testNS, - WithPullSubscriptionReady(sinkURI), - WithPullSubscriptionReadyStatus(corev1.ConditionTrue, "PullSubscriptionNoReady", ""), + NewPubSubPullSubscriptionWithNoDefaults(pubsubName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), + WithPubSubPullSubscriptionReadyStatus(corev1.ConditionTrue, "PullSubscriptionNoReady", ""), ), newSink(), }, diff --git a/pkg/reconciler/events/scheduler/scheduler_test.go b/pkg/reconciler/events/scheduler/scheduler_test.go index 08e3f61777..81392aca0f 100644 --- a/pkg/reconciler/events/scheduler/scheduler_test.go +++ b/pkg/reconciler/events/scheduler/scheduler_test.go @@ -178,16 +178,16 @@ func TestAllCases(t *testing.T) { ), }}, WantCreates: []runtime.Object{ - NewTopic(schedulerName, testNS, - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - WithTopicLabels(map[string]string{ + WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": schedulerName, }), - WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), }, WantPatches: []clientgotesting.PatchActionImpl{ @@ -206,8 +206,8 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicTopicID(testTopicID), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicTopicID(testTopicID), ), newSink(), }, @@ -237,9 +237,9 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), ), newSink(), }, @@ -270,10 +270,10 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicReady(""), - WithTopicProjectID(testProject), - WithTopicAddress(testTopicURI), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady(""), + WithPubSubTopicProjectID(testProject), + WithPubSubTopicAddress(testTopicURI), ), newSink(), }, @@ -304,10 +304,10 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicReady("garbaaaaage"), - WithTopicProjectID(testProject), - WithTopicAddress(testTopicURI), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady("garbaaaaage"), + WithPubSubTopicProjectID(testProject), + WithPubSubTopicAddress(testTopicURI), ), newSink(), }, @@ -338,9 +338,9 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicFailed(), - WithTopicProjectID(testProject), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicFailed(), + WithPubSubTopicProjectID(testProject), ), newSink(), }, @@ -371,9 +371,9 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicUnknown(), - WithTopicProjectID(testProject), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicUnknown(), + WithPubSubTopicProjectID(testProject), ), newSink(), }, @@ -405,10 +405,10 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), newSink(), }, @@ -425,21 +425,21 @@ func TestAllCases(t *testing.T) { ), }}, WantCreates: []runtime.Object{ - NewPullSubscriptionWithNoDefaults(schedulerName, testNS, - WithPullSubscriptionSpecWithNoDefaults(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscriptionWithNoDefaults(schedulerName, testNS, + WithPubSubPullSubscriptionSpecWithNoDefaults(pubsubv1alpha1.PullSubscriptionSpec{ Topic: testTopicID, PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, }, }), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionLabels(map[string]string{ + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": schedulerName}), - WithPullSubscriptionAnnotations(map[string]string{ + WithPubSubPullSubscriptionAnnotations(map[string]string{ "metrics-resource-group": resourceGroup, }), - WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + WithPubSubPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), }, WantPatches: []clientgotesting.PatchActionImpl{ @@ -458,12 +458,12 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(schedulerName, testNS), + NewPubSubPullSubscriptionWithNoDefaults(schedulerName, testNS), newSink(), }, Key: testNS + "/" + schedulerName, @@ -494,12 +494,12 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(schedulerName, testNS, WithPullSubscriptionFailed()), + NewPubSubPullSubscriptionWithNoDefaults(schedulerName, testNS, WithPubSubPullSubscriptionFailed()), newSink(), }, Key: testNS + "/" + schedulerName, @@ -530,12 +530,12 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(schedulerName, testNS, WithPullSubscriptionUnknown()), + NewPubSubPullSubscriptionWithNoDefaults(schedulerName, testNS, WithPubSubPullSubscriptionUnknown()), newSink(), }, Key: testNS + "/" + schedulerName, @@ -567,13 +567,13 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(schedulerName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(schedulerName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, @@ -613,13 +613,13 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(schedulerName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(schedulerName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, @@ -659,13 +659,13 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(schedulerName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(schedulerName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, @@ -705,13 +705,13 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(schedulerName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(schedulerName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, @@ -752,13 +752,13 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(schedulerName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(schedulerName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, @@ -798,13 +798,13 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceData(testData), WithCloudSchedulerSourceSchedule(onceAMinuteSchedule), ), - NewTopic(schedulerName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(schedulerName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(schedulerName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, @@ -845,13 +845,13 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceSinkURI(schedulerSinkURL), WithCloudSchedulerSourceDeletionTimestamp, ), - NewTopic(schedulerName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(schedulerName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(schedulerName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, @@ -881,13 +881,13 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceSinkURI(schedulerSinkURL), WithCloudSchedulerSourceDeletionTimestamp, ), - NewTopic(schedulerName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(schedulerName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(schedulerName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, @@ -917,13 +917,13 @@ func TestAllCases(t *testing.T) { WithCloudSchedulerSourceSinkURI(schedulerSinkURL), WithCloudSchedulerSourceDeletionTimestamp, ), - NewTopic(schedulerName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(schedulerName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(schedulerName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(schedulerName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, diff --git a/pkg/reconciler/events/storage/storage_test.go b/pkg/reconciler/events/storage/storage_test.go index 6b1b995ce2..e5639040ce 100644 --- a/pkg/reconciler/events/storage/storage_test.go +++ b/pkg/reconciler/events/storage/storage_test.go @@ -176,16 +176,16 @@ func TestAllCases(t *testing.T) { ), }}, WantCreates: []runtime.Object{ - NewTopic(storageName, testNS, - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + NewPubSubTopic(storageName, testNS, + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - WithTopicLabels(map[string]string{ + WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": storageName, }), - WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), }, WantPatches: []clientgotesting.PatchActionImpl{ @@ -203,8 +203,8 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceBucket(bucket), WithCloudStorageSourceSink(sinkGVK, sinkName), ), - NewTopic(storageName, testNS, - WithTopicTopicID(testTopicID), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicTopicID(testTopicID), ), newSink(), }, @@ -233,9 +233,9 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceBucket(bucket), WithCloudStorageSourceSink(sinkGVK, sinkName), ), - NewTopic(storageName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), ), newSink(), }, @@ -265,10 +265,10 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceBucket(bucket), WithCloudStorageSourceSink(sinkGVK, sinkName), ), - NewTopic(storageName, testNS, - WithTopicReady(""), - WithTopicProjectID(testProject), - WithTopicAddress(testTopicURI), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicReady(""), + WithPubSubTopicProjectID(testProject), + WithPubSubTopicAddress(testTopicURI), ), newSink(), }, @@ -298,10 +298,10 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceBucket(bucket), WithCloudStorageSourceSink(sinkGVK, sinkName), ), - NewTopic(storageName, testNS, - WithTopicReady("garbaaaaage"), - WithTopicProjectID(testProject), - WithTopicAddress(testTopicURI), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicReady("garbaaaaage"), + WithPubSubTopicProjectID(testProject), + WithPubSubTopicAddress(testTopicURI), ), newSink(), }, @@ -331,9 +331,9 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceBucket(bucket), WithCloudStorageSourceSink(sinkGVK, sinkName), ), - NewTopic(storageName, testNS, - WithTopicFailed(), - WithTopicProjectID(testProject), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicFailed(), + WithPubSubTopicProjectID(testProject), ), newSink(), }, @@ -363,9 +363,9 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceBucket(bucket), WithCloudStorageSourceSink(sinkGVK, sinkName), ), - NewTopic(storageName, testNS, - WithTopicUnknown(), - WithTopicProjectID(testProject), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicUnknown(), + WithPubSubTopicProjectID(testProject), ), newSink(), }, @@ -395,10 +395,10 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceBucket(bucket), WithCloudStorageSourceSink(sinkGVK, sinkName), ), - NewTopic(storageName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), newSink(), }, @@ -416,22 +416,22 @@ func TestAllCases(t *testing.T) { ), }}, WantCreates: []runtime.Object{ - NewPullSubscriptionWithNoDefaults(storageName, testNS, - WithPullSubscriptionSpecWithNoDefaults(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscriptionWithNoDefaults(storageName, testNS, + WithPubSubPullSubscriptionSpecWithNoDefaults(pubsubv1alpha1.PullSubscriptionSpec{ Topic: testTopicID, PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, }, }), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionLabels(map[string]string{ + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": storageName, }), - WithPullSubscriptionAnnotations(map[string]string{ + WithPubSubPullSubscriptionAnnotations(map[string]string{ "metrics-resource-group": resourceGroup, }), - WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + WithPubSubPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), }, WantPatches: []clientgotesting.PatchActionImpl{ @@ -450,12 +450,12 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceBucket(bucket), WithCloudStorageSourceSink(sinkGVK, sinkName), ), - NewTopic(storageName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(storageName, testNS), + NewPubSubPullSubscriptionWithNoDefaults(storageName, testNS), newSink(), }, Key: testNS + "/" + storageName, @@ -486,12 +486,12 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceBucket(bucket), WithCloudStorageSourceSink(sinkGVK, sinkName), ), - NewTopic(storageName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(storageName, testNS, WithPullSubscriptionFailed()), + NewPubSubPullSubscriptionWithNoDefaults(storageName, testNS, WithPubSubPullSubscriptionFailed()), }, Key: testNS + "/" + storageName, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ @@ -521,12 +521,12 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceBucket(bucket), WithCloudStorageSourceSink(sinkGVK, sinkName), ), - NewTopic(storageName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(storageName, testNS, WithPullSubscriptionUnknown()), + NewPubSubPullSubscriptionWithNoDefaults(storageName, testNS, WithPubSubPullSubscriptionUnknown()), }, Key: testNS + "/" + storageName, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ @@ -559,13 +559,13 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceSink(sinkGVK, sinkName), WithCloudStorageSourceEventTypes([]string{storagev1alpha1.CloudStorageSourceFinalize}), ), - NewTopic(storageName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(storageName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(storageName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, @@ -609,13 +609,13 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceSink(sinkGVK, sinkName), WithCloudStorageSourceEventTypes([]string{storagev1alpha1.CloudStorageSourceFinalize}), ), - NewTopic(storageName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(storageName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(storageName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, @@ -661,13 +661,13 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceSink(sinkGVK, sinkName), WithCloudStorageSourceEventTypes([]string{storagev1alpha1.CloudStorageSourceFinalize}), ), - NewTopic(storageName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(storageName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(storageName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, @@ -713,13 +713,13 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceSink(sinkGVK, sinkName), WithCloudStorageSourceEventTypes([]string{storagev1alpha1.CloudStorageSourceFinalize}), ), - NewTopic(storageName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(storageName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(storageName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, @@ -768,13 +768,13 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceTopicReady(testTopicID), WithDeletionTimestamp(), ), - NewTopic(storageName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(storageName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(storageName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, @@ -809,13 +809,13 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceTopicReady(testTopicID), WithDeletionTimestamp(), ), - NewTopic(storageName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(storageName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(storageName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, @@ -881,13 +881,13 @@ func TestAllCases(t *testing.T) { WithCloudStorageSourceTopicReady(testTopicID), WithDeletionTimestamp(), ), - NewTopic(storageName, testNS, - WithTopicReady(testTopicID), - WithTopicAddress(testTopicURI), - WithTopicProjectID(testProject), + NewPubSubTopic(storageName, testNS, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicAddress(testTopicURI), + WithPubSubTopicProjectID(testProject), ), - NewPullSubscriptionWithNoDefaults(storageName, testNS, - WithPullSubscriptionReady(sinkURI), + NewPubSubPullSubscriptionWithNoDefaults(storageName, testNS, + WithPubSubPullSubscriptionReady(sinkURI), ), newSink(), }, diff --git a/pkg/reconciler/pubsub/pullsubscription/keda/pullsubscription_test.go b/pkg/reconciler/pubsub/pullsubscription/keda/pullsubscription_test.go index f2e0a2f271..28630bd86c 100644 --- a/pkg/reconciler/pubsub/pullsubscription/keda/pullsubscription_test.go +++ b/pkg/reconciler/pubsub/pullsubscription/keda/pullsubscription_test.go @@ -126,21 +126,21 @@ func newSecret() *corev1.Secret { } func newPullSubscription(subscriptionId string) *pubsubv1alpha1.PullSubscription { - return NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + return NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ Topic: testTopicID, PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, }), - WithPullSubscriptionSubscriptionID(subscriptionId), - WithInitPullSubscriptionConditions, - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionSubscriptionID(subscriptionId), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), ) } @@ -203,17 +203,17 @@ func TestAllCases(t *testing.T) { }, { Name: "cannot get sink", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), ), newSecret(), }, @@ -227,40 +227,40 @@ func TestAllCases(t *testing.T) { patchFinalizers(testNS, sourceName, resourceGroup), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), // Updates - WithPullSubscriptionStatusObservedGeneration(generation), - WithInitPullSubscriptionConditions, - WithPullSubscriptionSinkNotFound(), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionSinkNotFound(), ), }}, }, { Name: "create client fails", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), ), newSink(), newSecret(), @@ -276,25 +276,25 @@ func TestAllCases(t *testing.T) { }, }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionStatusObservedGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), - WithPullSubscriptionTransformerURI(nil), - WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "client-create-induced-error"))), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPubSubPullSubscriptionTransformerURI(nil), + WithPubSubPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "client-create-induced-error"))), }}, WantPatches: []clientgotesting.PatchActionImpl{ patchFinalizers(testNS, sourceName, resourceGroup), @@ -302,20 +302,20 @@ func TestAllCases(t *testing.T) { }, { Name: "topic exists fails", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), ), newSink(), newSecret(), @@ -333,25 +333,25 @@ func TestAllCases(t *testing.T) { }, }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionStatusObservedGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), - WithPullSubscriptionTransformerURI(nil), - WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "topic-exists-induced-error"))), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPubSubPullSubscriptionTransformerURI(nil), + WithPubSubPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "topic-exists-induced-error"))), }}, WantPatches: []clientgotesting.PatchActionImpl{ patchFinalizers(testNS, sourceName, resourceGroup), @@ -359,20 +359,20 @@ func TestAllCases(t *testing.T) { }, { Name: "topic does not exist", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), ), newSink(), newSecret(), @@ -390,25 +390,25 @@ func TestAllCases(t *testing.T) { }, }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionStatusObservedGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), - WithPullSubscriptionTransformerURI(nil), - WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: Topic %q does not exist", failedToReconcileSubscriptionMsg, testTopicID))), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPubSubPullSubscriptionTransformerURI(nil), + WithPubSubPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: Topic %q does not exist", failedToReconcileSubscriptionMsg, testTopicID))), }}, WantPatches: []clientgotesting.PatchActionImpl{ patchFinalizers(testNS, sourceName, resourceGroup), @@ -416,20 +416,20 @@ func TestAllCases(t *testing.T) { }, { Name: "subscription exists fails", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), ), newSink(), newSecret(), @@ -447,25 +447,25 @@ func TestAllCases(t *testing.T) { }, }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionStatusObservedGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), - WithPullSubscriptionTransformerURI(nil), - WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "subscription-exists-induced-error"))), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPubSubPullSubscriptionTransformerURI(nil), + WithPubSubPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "subscription-exists-induced-error"))), }}, WantPatches: []clientgotesting.PatchActionImpl{ patchFinalizers(testNS, sourceName, resourceGroup), @@ -473,20 +473,20 @@ func TestAllCases(t *testing.T) { }, { Name: "create subscription fails", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), ), newSink(), newSecret(), @@ -505,25 +505,25 @@ func TestAllCases(t *testing.T) { }, }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionStatusObservedGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), - WithPullSubscriptionTransformerURI(nil), - WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "subscription-create-induced-error"))), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPubSubPullSubscriptionTransformerURI(nil), + WithPubSubPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "subscription-create-induced-error"))), }}, WantPatches: []clientgotesting.PatchActionImpl{ patchFinalizers(testNS, sourceName, resourceGroup), @@ -552,27 +552,27 @@ func TestAllCases(t *testing.T) { newReceiveAdapter(context.Background(), testImage, nil), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), - WithPullSubscriptionTransformerURI(nil), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPubSubPullSubscriptionTransformerURI(nil), // Updates - WithPullSubscriptionStatusObservedGeneration(generation), - WithPullSubscriptionMarkSubscribed(testSubscriptionID), - WithPullSubscriptionMarkDeployed, + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPubSubPullSubscriptionMarkDeployed, ), }}, WantPatches: []clientgotesting.PatchActionImpl{ @@ -581,18 +581,18 @@ func TestAllCases(t *testing.T) { }, { Name: "successful create - reuse existing receive adapter - match", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), ), newSink(), newSecret(), @@ -614,26 +614,26 @@ func TestAllCases(t *testing.T) { Eventf(corev1.EventTypeNormal, "PullSubscriptionReconciled", `PullSubscription reconciled: "%s/%s"`, testNS, sourceName), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSubscribed(testSubscriptionID), - WithPullSubscriptionMarkDeployed, - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), - WithPullSubscriptionTransformerURI(nil), - WithPullSubscriptionStatusObservedGeneration(generation), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPubSubPullSubscriptionMarkDeployed, + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPubSubPullSubscriptionTransformerURI(nil), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), ), }}, WantPatches: []clientgotesting.PatchActionImpl{ @@ -642,19 +642,19 @@ func TestAllCases(t *testing.T) { }, { Name: "successful create - reuse existing receive adapter - mismatch", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionTransformer(transformerGVK, transformerName), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionTransformer(transformerGVK, transformerName), ), newSink(), newTransformer(), @@ -685,26 +685,26 @@ func TestAllCases(t *testing.T) { Object: newReceiveAdapter(context.Background(), testImage, transformerURI), }}, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionTransformer(transformerGVK, transformerName), - WithPullSubscriptionMarkSubscribed(testSubscriptionID), - WithPullSubscriptionMarkDeployed, - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkTransformer(transformerURI), - WithPullSubscriptionStatusObservedGeneration(generation), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionTransformer(transformerGVK, transformerName), + WithPubSubPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPubSubPullSubscriptionMarkDeployed, + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkTransformer(transformerURI), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), ), }}, WantPatches: []clientgotesting.PatchActionImpl{ @@ -713,22 +713,22 @@ func TestAllCases(t *testing.T) { }, { Name: "deleting - failed to delete subscription", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSubscribed(testSubscriptionID), - WithPullSubscriptionMarkDeployed, - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionDeleted, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPubSubPullSubscriptionMarkDeployed, + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionDeleted, ), newSecret(), }, @@ -751,23 +751,23 @@ func TestAllCases(t *testing.T) { }, { Name: "successfully deleted subscription", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSubscribed(testSubscriptionID), - WithPullSubscriptionMarkDeployed, - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionSubscriptionID(""), - WithPullSubscriptionDeleted, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPubSubPullSubscriptionMarkDeployed, + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionSubscriptionID(""), + WithPubSubPullSubscriptionDeleted, ), newSecret(), }, @@ -817,9 +817,9 @@ func mockDiscoveryFunc(_ discovery.DiscoveryInterface, _ schema.GroupVersion) er } func newReceiveAdapter(ctx context.Context, image string, transformer *apis.URL) runtime.Object { - source := NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionAnnotations(map[string]string{ + source := NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionAnnotations(map[string]string{ v1alpha1.AutoscalingClassAnnotation: v1alpha1.KEDA, v1alpha1.AutoscalingMinScaleAnnotation: "0", v1alpha1.AutoscalingMaxScaleAnnotation: "3", @@ -827,7 +827,7 @@ func newReceiveAdapter(ctx context.Context, image string, transformer *apis.URL) v1alpha1.KedaAutoscalingCooldownPeriodAnnotation: "60", v1alpha1.KedaAutoscalingPollingIntervalAnnotation: "30", }), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, diff --git a/pkg/reconciler/pubsub/pullsubscription/keda/resources/scaled_object_test.go b/pkg/reconciler/pubsub/pullsubscription/keda/resources/scaled_object_test.go index dad29a76b7..890100179d 100644 --- a/pkg/reconciler/pubsub/pullsubscription/keda/resources/scaled_object_test.go +++ b/pkg/reconciler/pubsub/pullsubscription/keda/resources/scaled_object_test.go @@ -43,10 +43,10 @@ func newAnnotations() map[string]string { } func newPullSubscription() *v1alpha1.PullSubscription { - return NewPullSubscription("psname", "psnamespace", - WithPullSubscriptionUID("psuid"), - WithPullSubscriptionAnnotations(newAnnotations()), - WithPullSubscriptionSubscriptionID("subscriptionId"), + return NewPubSubPullSubscription("psname", "psnamespace", + WithPubSubPullSubscriptionUID("psuid"), + WithPubSubPullSubscriptionAnnotations(newAnnotations()), + WithPubSubPullSubscriptionSubscriptionID("subscriptionId"), ) } diff --git a/pkg/reconciler/pubsub/pullsubscription/static/pullsubscription_test.go b/pkg/reconciler/pubsub/pullsubscription/static/pullsubscription_test.go index b8263e89a7..078b0d6534 100644 --- a/pkg/reconciler/pubsub/pullsubscription/static/pullsubscription_test.go +++ b/pkg/reconciler/pubsub/pullsubscription/static/pullsubscription_test.go @@ -167,16 +167,16 @@ func TestAllCases(t *testing.T) { }, { Name: "cannot get sink", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), ), newSecret(), }, @@ -190,38 +190,38 @@ func TestAllCases(t *testing.T) { patchFinalizers(testNS, sourceName, resourceGroup), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionStatusObservedGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), // updates - WithInitPullSubscriptionConditions, - WithPullSubscriptionSinkNotFound(), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionSinkNotFound(), ), }}, }, { Name: "create client fails", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), ), newSink(), newSecret(), @@ -237,24 +237,24 @@ func TestAllCases(t *testing.T) { }, }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionStatusObservedGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), - WithPullSubscriptionTransformerURI(nil), - WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "client-create-induced-error"))), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPubSubPullSubscriptionTransformerURI(nil), + WithPubSubPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "client-create-induced-error"))), }}, WantPatches: []clientgotesting.PatchActionImpl{ patchFinalizers(testNS, sourceName, resourceGroup), @@ -262,19 +262,19 @@ func TestAllCases(t *testing.T) { }, { Name: "topic exists fails", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), ), newSink(), newSecret(), @@ -295,41 +295,41 @@ func TestAllCases(t *testing.T) { patchFinalizers(testNS, sourceName, resourceGroup), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionStatusObservedGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), - WithPullSubscriptionTransformerURI(nil), - WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "topic-exists-induced-error"))), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPubSubPullSubscriptionTransformerURI(nil), + WithPubSubPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "topic-exists-induced-error"))), }}, }, { Name: "topic does not exist", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), ), newSink(), newSecret(), @@ -350,41 +350,41 @@ func TestAllCases(t *testing.T) { patchFinalizers(testNS, sourceName, resourceGroup), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionStatusObservedGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), - WithPullSubscriptionTransformerURI(nil), - WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: Topic %q does not exist", failedToReconcileSubscriptionMsg, testTopicID))), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPubSubPullSubscriptionTransformerURI(nil), + WithPubSubPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: Topic %q does not exist", failedToReconcileSubscriptionMsg, testTopicID))), }}, }, { Name: "subscription exists fails", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), ), newSink(), newSecret(), @@ -405,41 +405,41 @@ func TestAllCases(t *testing.T) { patchFinalizers(testNS, sourceName, resourceGroup), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionStatusObservedGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), - WithPullSubscriptionTransformerURI(nil), - WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "subscription-exists-induced-error"))), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPubSubPullSubscriptionTransformerURI(nil), + WithPubSubPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "subscription-exists-induced-error"))), }}, }, { Name: "create subscription fails", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), ), newSink(), newSecret(), @@ -461,41 +461,41 @@ func TestAllCases(t *testing.T) { patchFinalizers(testNS, sourceName, resourceGroup), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionStatusObservedGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), - WithPullSubscriptionTransformerURI(nil), - WithPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "subscription-create-induced-error"))), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPubSubPullSubscriptionTransformerURI(nil), + WithPubSubPullSubscriptionMarkNoSubscription("SubscriptionReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileSubscriptionMsg, "subscription-create-induced-error"))), }}, }, { Name: "successfully created subscription", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), ), newSink(), newSecret(), @@ -516,26 +516,26 @@ func TestAllCases(t *testing.T) { newReceiveAdapter(context.Background(), testImage, nil), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), - WithPullSubscriptionTransformerURI(nil), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPubSubPullSubscriptionTransformerURI(nil), // Updates - WithPullSubscriptionStatusObservedGeneration(generation), - WithPullSubscriptionMarkSubscribed(testSubscriptionID), - WithPullSubscriptionMarkDeployed, + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPubSubPullSubscriptionMarkDeployed, ), }}, WantPatches: []clientgotesting.PatchActionImpl{ @@ -544,17 +544,17 @@ func TestAllCases(t *testing.T) { }, { Name: "successful create - reuse existing receive adapter - match", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), ), newSink(), newSecret(), @@ -576,42 +576,42 @@ func TestAllCases(t *testing.T) { patchFinalizers(testNS, sourceName, resourceGroup), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSubscribed(testSubscriptionID), - WithPullSubscriptionMarkDeployed, - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), - WithPullSubscriptionTransformerURI(nil), - WithPullSubscriptionStatusObservedGeneration(generation), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPubSubPullSubscriptionMarkDeployed, + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkNoTransformer("TransformerNil", "Transformer is nil"), + WithPubSubPullSubscriptionTransformerURI(nil), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), ), }}, }, { Name: "successful create - reuse existing receive adapter - mismatch", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionTransformer(transformerGVK, transformerName), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionTransformer(transformerGVK, transformerName), ), newSink(), newTransformer(), @@ -642,46 +642,46 @@ func TestAllCases(t *testing.T) { patchFinalizers(testNS, sourceName, resourceGroup), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), //WithPullSubscriptionFinalizers(resourceGroup), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithInitPullSubscriptionConditions, - WithPullSubscriptionProjectID(testProject), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionTransformer(transformerGVK, transformerName), - WithPullSubscriptionMarkSubscribed(testSubscriptionID), - WithPullSubscriptionMarkDeployed, - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionMarkTransformer(transformerURI), - WithPullSubscriptionStatusObservedGeneration(generation), + WithPubSubInitPullSubscriptionConditions, + WithPubSubPullSubscriptionProjectID(testProject), + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionTransformer(transformerGVK, transformerName), + WithPubSubPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPubSubPullSubscriptionMarkDeployed, + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionMarkTransformer(transformerURI), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), ), }}, }, { Name: "deleting - failed to delete subscription", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSubscribed(testSubscriptionID), - WithPullSubscriptionMarkDeployed, - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionDeleted, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPubSubPullSubscriptionMarkDeployed, + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionDeleted, ), newSecret(), }, @@ -704,22 +704,22 @@ func TestAllCases(t *testing.T) { }, { Name: "successfully deleted subscription", Objects: []runtime.Object{ - NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionStatusObservedGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSubscribed(testSubscriptionID), - WithPullSubscriptionMarkDeployed, - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionDeleted, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPubSubPullSubscriptionMarkDeployed, + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionDeleted, ), newSecret(), }, @@ -736,23 +736,23 @@ func TestAllCases(t *testing.T) { Key: testNS + "/" + sourceName, WantEvents: nil, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionObjectMetaGeneration(generation), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + Object: NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionObjectMetaGeneration(generation), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, }, Topic: testTopicID, }), - WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMarkSubscribed(testSubscriptionID), - WithPullSubscriptionSubscriptionID(""), - WithPullSubscriptionMarkDeployed, - WithPullSubscriptionMarkSink(sinkURI), - WithPullSubscriptionStatusObservedGeneration(generation), - WithPullSubscriptionDeleted, + WithPubSubPullSubscriptionSink(sinkGVK, sinkName), + WithPubSubPullSubscriptionMarkSubscribed(testSubscriptionID), + WithPubSubPullSubscriptionSubscriptionID(""), + WithPubSubPullSubscriptionMarkDeployed, + WithPubSubPullSubscriptionMarkSink(sinkURI), + WithPubSubPullSubscriptionStatusObservedGeneration(generation), + WithPubSubPullSubscriptionDeleted, ), }}, }} @@ -781,9 +781,9 @@ func TestAllCases(t *testing.T) { } func newReceiveAdapter(ctx context.Context, image string, transformer *apis.URL) runtime.Object { - source := NewPullSubscription(sourceName, testNS, - WithPullSubscriptionUID(sourceUID), - WithPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ + source := NewPubSubPullSubscription(sourceName, testNS, + WithPubSubPullSubscriptionUID(sourceUID), + WithPubSubPullSubscriptionSpec(pubsubv1alpha1.PullSubscriptionSpec{ PubSubSpec: duckv1alpha1.PubSubSpec{ Secret: &secret, Project: testProject, diff --git a/pkg/reconciler/pubsub/reconciler_test.go b/pkg/reconciler/pubsub/reconciler_test.go index ea31fcdd30..6db6c1c426 100644 --- a/pkg/reconciler/pubsub/reconciler_test.go +++ b/pkg/reconciler/pubsub/reconciler_test.go @@ -90,472 +90,472 @@ func TestCreates(t *testing.T) { wantCreates []runtime.Object }{{ name: "topic does not exist, created, not yet been reconciled", - expectedTopic: rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + expectedTopic: rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Secret: &secret, Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), expectedPS: nil, expectedErr: fmt.Sprintf("Topic %q has not yet been reconciled", name), wantCreates: []runtime.Object{ - rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), }, }, { name: "topic exists but is not yet been reconciled", objects: []runtime.Object{ - rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), }, - expectedTopic: rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + expectedTopic: rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Secret: &secret, Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), expectedPS: nil, expectedErr: fmt.Sprintf("Topic %q has not yet been reconciled", name), }, { name: "topic exists and is ready but no projectid", objects: []runtime.Object{ - rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicReady(testTopicID), - rectesting.WithTopicAddress(testTopicURI), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicReady(testTopicID), + rectesting.WithPubSubTopicAddress(testTopicURI), ), }, - expectedTopic: rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + expectedTopic: rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Secret: &secret, Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicReady(testTopicID), - rectesting.WithTopicAddress(testTopicURI), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicReady(testTopicID), + rectesting.WithPubSubTopicAddress(testTopicURI), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), expectedPS: nil, expectedErr: fmt.Sprintf("Topic %q did not expose projectid", name), }, { name: "topic exists and the status of topic is false", objects: []runtime.Object{ - rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicProjectID(testProjectID), - rectesting.WithTopicFailed(), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicProjectID(testProjectID), + rectesting.WithPubSubTopicFailed(), ), }, - expectedTopic: rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + expectedTopic: rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Secret: &secret, Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicFailed(), - rectesting.WithTopicProjectID(testProjectID), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicFailed(), + rectesting.WithPubSubTopicProjectID(testProjectID), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), expectedPS: nil, expectedErr: fmt.Sprintf("the status of Topic %q is False", name), }, { name: "topic exists and the status of topic is unknown", objects: []runtime.Object{ - rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicProjectID(testProjectID), - rectesting.WithTopicUnknown(), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicProjectID(testProjectID), + rectesting.WithPubSubTopicUnknown(), ), }, - expectedTopic: rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + expectedTopic: rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Secret: &secret, Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicUnknown(), - rectesting.WithTopicProjectID(testProjectID), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicUnknown(), + rectesting.WithPubSubTopicProjectID(testProjectID), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), expectedPS: nil, expectedErr: fmt.Sprintf("the status of Topic %q is Unknown", name), }, { name: "topic exists and is ready but no topicid", objects: []runtime.Object{ - rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicProjectID(testProjectID), - rectesting.WithTopicReady(""), - rectesting.WithTopicAddress(testTopicURI), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicProjectID(testProjectID), + rectesting.WithPubSubTopicReady(""), + rectesting.WithPubSubTopicAddress(testTopicURI), ), }, - expectedTopic: rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + expectedTopic: rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Secret: &secret, Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicReady(""), - rectesting.WithTopicProjectID(testProjectID), - rectesting.WithTopicAddress(testTopicURI), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicReady(""), + rectesting.WithPubSubTopicProjectID(testProjectID), + rectesting.WithPubSubTopicAddress(testTopicURI), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), expectedPS: nil, expectedErr: fmt.Sprintf("Topic %q did not expose topicid", name), }, { name: "topic exists and is ready, pullsubscription created, not yet been reconciled", objects: []runtime.Object{ - rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicProjectID(testProjectID), - rectesting.WithTopicReady(testTopicID), - rectesting.WithTopicAddress(testTopicURI), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicProjectID(testProjectID), + rectesting.WithPubSubTopicReady(testTopicID), + rectesting.WithPubSubTopicAddress(testTopicURI), ), }, - expectedTopic: rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + expectedTopic: rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Secret: &secret, Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicReady(testTopicID), - rectesting.WithTopicProjectID(testProjectID), - rectesting.WithTopicAddress(testTopicURI), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicReady(testTopicID), + rectesting.WithPubSubTopicProjectID(testProjectID), + rectesting.WithPubSubTopicAddress(testTopicURI), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), - expectedPS: rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, - rectesting.WithPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ + expectedPS: rectesting.NewPubSubPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPubSubPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ Topic: testTopicID, PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, }, }), - rectesting.WithPullSubscriptionLabels(map[string]string{ + rectesting.WithPubSubPullSubscriptionLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithPullSubscriptionAnnotations(map[string]string{ + rectesting.WithPubSubPullSubscriptionAnnotations(map[string]string{ "metrics-resource-group": resourceGroup, }), - rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), expectedErr: fmt.Sprintf("%s: PullSubscription %q has not yet been reconciled", failedToPropagatePullSubscriptionStatusMsg, name), wantCreates: []runtime.Object{ - rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, - rectesting.WithPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ + rectesting.NewPubSubPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPubSubPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ Topic: testTopicID, PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, }, }), - rectesting.WithPullSubscriptionLabels(map[string]string{ + rectesting.WithPubSubPullSubscriptionLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithPullSubscriptionAnnotations(map[string]string{ + rectesting.WithPubSubPullSubscriptionAnnotations(map[string]string{ "metrics-resource-group": resourceGroup, }), - rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), }, }, { name: "topic exists and is ready, pullsubscription exists, not yet been reconciled", objects: []runtime.Object{ - rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicProjectID(testProjectID), - rectesting.WithTopicReady(testTopicID), - rectesting.WithTopicAddress(testTopicURI), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicProjectID(testProjectID), + rectesting.WithPubSubTopicReady(testTopicID), + rectesting.WithPubSubTopicAddress(testTopicURI), ), - rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, - rectesting.WithPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ + rectesting.NewPubSubPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPubSubPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ Topic: testTopicID, PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, }, }), - rectesting.WithPullSubscriptionLabels(map[string]string{ + rectesting.WithPubSubPullSubscriptionLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithPullSubscriptionAnnotations(map[string]string{ + rectesting.WithPubSubPullSubscriptionAnnotations(map[string]string{ "metrics-resource-group": resourceGroup, }), - rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), }, - expectedTopic: rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + expectedTopic: rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Secret: &secret, Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicReady(testTopicID), - rectesting.WithTopicProjectID(testProjectID), - rectesting.WithTopicAddress(testTopicURI), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicReady(testTopicID), + rectesting.WithPubSubTopicProjectID(testProjectID), + rectesting.WithPubSubTopicAddress(testTopicURI), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), - expectedPS: rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, - rectesting.WithPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ + expectedPS: rectesting.NewPubSubPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPubSubPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ Topic: testTopicID, PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, }, }), - rectesting.WithPullSubscriptionLabels(map[string]string{ + rectesting.WithPubSubPullSubscriptionLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithPullSubscriptionAnnotations(map[string]string{ + rectesting.WithPubSubPullSubscriptionAnnotations(map[string]string{ "metrics-resource-group": resourceGroup, }), - rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), expectedErr: fmt.Sprintf("%s: PullSubscription %q has not yet been reconciled", failedToPropagatePullSubscriptionStatusMsg, name), }, { name: "topic exists and is ready, pullsubscription exists and the status is false", objects: []runtime.Object{ - rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicProjectID(testProjectID), - rectesting.WithTopicReady(testTopicID), - rectesting.WithTopicAddress(testTopicURI), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicProjectID(testProjectID), + rectesting.WithPubSubTopicReady(testTopicID), + rectesting.WithPubSubTopicAddress(testTopicURI), ), - rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, - rectesting.WithPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ + rectesting.NewPubSubPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPubSubPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ Topic: testTopicID, PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, }, }), - rectesting.WithPullSubscriptionLabels(map[string]string{ + rectesting.WithPubSubPullSubscriptionLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithPullSubscriptionAnnotations(map[string]string{ + rectesting.WithPubSubPullSubscriptionAnnotations(map[string]string{ "metrics-resource-group": resourceGroup, }), - rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithPullSubscriptionFailed(), + rectesting.WithPubSubPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubPullSubscriptionFailed(), ), }, - expectedTopic: rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + expectedTopic: rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Secret: &secret, Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicReady(testTopicID), - rectesting.WithTopicProjectID(testProjectID), - rectesting.WithTopicAddress(testTopicURI), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicReady(testTopicID), + rectesting.WithPubSubTopicProjectID(testProjectID), + rectesting.WithPubSubTopicAddress(testTopicURI), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), - expectedPS: rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, - rectesting.WithPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ + expectedPS: rectesting.NewPubSubPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPubSubPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ Topic: testTopicID, PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, }, }), - rectesting.WithPullSubscriptionLabels(map[string]string{ + rectesting.WithPubSubPullSubscriptionLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithPullSubscriptionAnnotations(map[string]string{ + rectesting.WithPubSubPullSubscriptionAnnotations(map[string]string{ "metrics-resource-group": resourceGroup, }), - rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithPullSubscriptionFailed(), + rectesting.WithPubSubPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubPullSubscriptionFailed(), ), expectedErr: fmt.Sprintf("%s: the status of PullSubscription %q is False", failedToPropagatePullSubscriptionStatusMsg, name), }, { name: "topic exists and is ready, pullsubscription exists and the status is unknown", objects: []runtime.Object{ - rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicProjectID(testProjectID), - rectesting.WithTopicReady(testTopicID), - rectesting.WithTopicAddress(testTopicURI), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicProjectID(testProjectID), + rectesting.WithPubSubTopicReady(testTopicID), + rectesting.WithPubSubTopicAddress(testTopicURI), ), - rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, - rectesting.WithPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ + rectesting.NewPubSubPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPubSubPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ Topic: testTopicID, PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, }, }), - rectesting.WithPullSubscriptionLabels(map[string]string{ + rectesting.WithPubSubPullSubscriptionLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithPullSubscriptionAnnotations(map[string]string{ + rectesting.WithPubSubPullSubscriptionAnnotations(map[string]string{ "metrics-resource-group": resourceGroup, }), - rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithPullSubscriptionUnknown(), + rectesting.WithPubSubPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubPullSubscriptionUnknown(), ), }, - expectedTopic: rectesting.NewTopic(name, testNS, - rectesting.WithTopicSpec(pubsubsourcev1alpha1.TopicSpec{ + expectedTopic: rectesting.NewPubSubTopic(name, testNS, + rectesting.WithPubSubTopicSpec(pubsubsourcev1alpha1.TopicSpec{ Secret: &secret, Topic: testTopicID, PropagationPolicy: "CreateDelete", }), - rectesting.WithTopicLabels(map[string]string{ + rectesting.WithPubSubTopicLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithTopicReady(testTopicID), - rectesting.WithTopicProjectID(testProjectID), - rectesting.WithTopicAddress(testTopicURI), - rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubTopicReady(testTopicID), + rectesting.WithPubSubTopicProjectID(testProjectID), + rectesting.WithPubSubTopicAddress(testTopicURI), + rectesting.WithPubSubTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), ), - expectedPS: rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, - rectesting.WithPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ + expectedPS: rectesting.NewPubSubPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPubSubPullSubscriptionSpecWithNoDefaults(pubsubsourcev1alpha1.PullSubscriptionSpec{ Topic: testTopicID, PubSubSpec: v1alpha1.PubSubSpec{ Secret: &secret, }, }), - rectesting.WithPullSubscriptionLabels(map[string]string{ + rectesting.WithPubSubPullSubscriptionLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": name, }), - rectesting.WithPullSubscriptionAnnotations(map[string]string{ + rectesting.WithPubSubPullSubscriptionAnnotations(map[string]string{ "metrics-resource-group": resourceGroup, }), - rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), - rectesting.WithPullSubscriptionUnknown(), + rectesting.WithPubSubPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPubSubPullSubscriptionUnknown(), ), expectedErr: fmt.Sprintf("%s: the status of PullSubscription %q is Unknown", failedToPropagatePullSubscriptionStatusMsg, name), }} diff --git a/pkg/reconciler/pubsub/topic/topic_test.go b/pkg/reconciler/pubsub/topic/topic_test.go index 7516f94f46..af99bbe86f 100644 --- a/pkg/reconciler/pubsub/topic/topic_test.go +++ b/pkg/reconciler/pubsub/topic/topic_test.go @@ -132,14 +132,14 @@ func TestAllCases(t *testing.T) { }, { Name: "create client fails", Objects: []runtime.Object{ - NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("NoCreateNoDelete"), + WithPubSubTopicPropagationPolicy("NoCreateNoDelete"), ), newSink(), newSecret(), @@ -158,30 +158,30 @@ func TestAllCases(t *testing.T) { patchFinalizers(testNS, topicName, resourceGroup), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicProjectID(testProject), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Object: NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicProjectID(testProject), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("NoCreateNoDelete"), + WithPubSubTopicPropagationPolicy("NoCreateNoDelete"), // Updates - WithInitTopicConditions, - WithTopicNoTopic("TopicReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileTopicMsg, "create-client-induced-error"))), + WithPubSubInitTopicConditions, + WithPubSubTopicNoTopic("TopicReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileTopicMsg, "create-client-induced-error"))), }}, }, { Name: "verify topic exists fails", Objects: []runtime.Object{ - NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("NoCreateNoDelete"), + WithPubSubTopicPropagationPolicy("NoCreateNoDelete"), ), newSink(), newSecret(), @@ -202,30 +202,30 @@ func TestAllCases(t *testing.T) { patchFinalizers(testNS, topicName, resourceGroup), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicProjectID(testProject), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Object: NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicProjectID(testProject), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("NoCreateNoDelete"), + WithPubSubTopicPropagationPolicy("NoCreateNoDelete"), // Updates - WithInitTopicConditions, - WithTopicNoTopic("TopicReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileTopicMsg, "topic-exists-induced-error"))), + WithPubSubInitTopicConditions, + WithPubSubTopicNoTopic("TopicReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileTopicMsg, "topic-exists-induced-error"))), }}, }, { Name: "topic does not exist and propagation policy is NoCreateNoDelete", Objects: []runtime.Object{ - NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("NoCreateNoDelete"), + WithPubSubTopicPropagationPolicy("NoCreateNoDelete"), ), newSink(), newSecret(), @@ -239,30 +239,30 @@ func TestAllCases(t *testing.T) { patchFinalizers(testNS, topicName, resourceGroup), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicProjectID(testProject), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Object: NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicProjectID(testProject), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("NoCreateNoDelete"), + WithPubSubTopicPropagationPolicy("NoCreateNoDelete"), // Updates - WithInitTopicConditions, - WithTopicNoTopic("TopicReconcileFailed", fmt.Sprintf("%s: Topic %q does not exist and the topic policy doesn't allow creation", failedToReconcileTopicMsg, testTopicID))), + WithPubSubInitTopicConditions, + WithPubSubTopicNoTopic("TopicReconcileFailed", fmt.Sprintf("%s: Topic %q does not exist and the topic policy doesn't allow creation", failedToReconcileTopicMsg, testTopicID))), }}, }, { Name: "create topic fails", Objects: []runtime.Object{ - NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("CreateNoDelete"), + WithPubSubTopicPropagationPolicy("CreateNoDelete"), ), newSink(), newSecret(), @@ -281,30 +281,30 @@ func TestAllCases(t *testing.T) { patchFinalizers(testNS, topicName, resourceGroup), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicProjectID(testProject), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Object: NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicProjectID(testProject), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("CreateNoDelete"), + WithPubSubTopicPropagationPolicy("CreateNoDelete"), // Updates - WithInitTopicConditions, - WithTopicNoTopic("TopicReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileTopicMsg, "create-topic-induced-error"))), + WithPubSubInitTopicConditions, + WithPubSubTopicNoTopic("TopicReconcileFailed", fmt.Sprintf("%s: %s", failedToReconcileTopicMsg, "create-topic-induced-error"))), }}, }, { Name: "publisher has not yet been reconciled", Objects: []runtime.Object{ - NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("CreateNoDelete"), + WithPubSubTopicPropagationPolicy("CreateNoDelete"), ), newSink(), newSecret(), @@ -321,32 +321,32 @@ func TestAllCases(t *testing.T) { newPublisher(), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicProjectID(testProject), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Object: NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicProjectID(testProject), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("CreateNoDelete"), + WithPubSubTopicPropagationPolicy("CreateNoDelete"), // Updates - WithInitTopicConditions, - WithTopicReady(testTopicID), - WithTopicPublisherNotConfigured()), + WithPubSubInitTopicConditions, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicPublisherNotConfigured()), }}, }, { Name: "the status of publisher is false", Objects: []runtime.Object{ - NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("CreateNoDelete"), + WithPubSubTopicPropagationPolicy("CreateNoDelete"), ), newSink(), newSecret(), @@ -366,31 +366,31 @@ func TestAllCases(t *testing.T) { newPublisher(), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicProjectID(testProject), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Object: NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicProjectID(testProject), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("CreateNoDelete"), + WithPubSubTopicPropagationPolicy("CreateNoDelete"), // Updates - WithInitTopicConditions, - WithTopicReady(testTopicID), - WithTopicPublisherNotDeployed("PublisherNotDeployed", "PublisherNotDeployed")), + WithPubSubInitTopicConditions, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicPublisherNotDeployed("PublisherNotDeployed", "PublisherNotDeployed")), }}, }, { Name: "the status of publisher is unknown", Objects: []runtime.Object{ - NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("CreateNoDelete"), + WithPubSubTopicPropagationPolicy("CreateNoDelete"), ), newSink(), newSecret(), @@ -410,31 +410,31 @@ func TestAllCases(t *testing.T) { newPublisher(), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicProjectID(testProject), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Object: NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicProjectID(testProject), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("CreateNoDelete"), + WithPubSubTopicPropagationPolicy("CreateNoDelete"), // Updates - WithInitTopicConditions, - WithTopicReady(testTopicID), - WithTopicPublisherUnknown("PublisherUnknown", "PublisherUnknown")), + WithPubSubInitTopicConditions, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicPublisherUnknown("PublisherUnknown", "PublisherUnknown")), }}, }, { Name: "topic successfully reconciles and is ready", Objects: []runtime.Object{ - NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("CreateNoDelete"), + WithPubSubTopicPropagationPolicy("CreateNoDelete"), ), newSink(), newSecret(), @@ -454,32 +454,32 @@ func TestAllCases(t *testing.T) { newPublisher(), }, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicProjectID(testProject), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Object: NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicProjectID(testProject), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("CreateNoDelete"), + WithPubSubTopicPropagationPolicy("CreateNoDelete"), // Updates - WithInitTopicConditions, - WithTopicReady(testTopicID), - WithTopicPublisherDeployed, - WithTopicAddress(testTopicURI)), + WithPubSubInitTopicConditions, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicPublisherDeployed, + WithPubSubTopicAddress(testTopicURI)), }}, }, { Name: "topic successfully reconciles and reuses existing publisher", Objects: []runtime.Object{ - NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("CreateNoDelete"), + WithPubSubTopicPropagationPolicy("CreateNoDelete"), ), newSink(), newSecret(), @@ -499,33 +499,33 @@ func TestAllCases(t *testing.T) { }, WithReactors: []clientgotesting.ReactionFunc{}, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ - Object: NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicProjectID(testProject), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + Object: NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicProjectID(testProject), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("CreateNoDelete"), + WithPubSubTopicPropagationPolicy("CreateNoDelete"), // Updates - WithInitTopicConditions, - WithTopicReady(testTopicID), - WithTopicPublisherDeployed, - WithTopicAddress(testTopicURI)), + WithPubSubInitTopicConditions, + WithPubSubTopicReady(testTopicID), + WithPubSubTopicPublisherDeployed, + WithPubSubTopicAddress(testTopicURI)), }}, }, { Name: "delete topic - policy CreateNoDelete", Objects: []runtime.Object{ - NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("CreateNoDelete"), - WithTopicDeleted, + WithPubSubTopicPropagationPolicy("CreateNoDelete"), + WithPubSubTopicDeleted, ), newSink(), newSecret(), @@ -536,16 +536,16 @@ func TestAllCases(t *testing.T) { }, { Name: "delete topic - policy CreateDelete", Objects: []runtime.Object{ - NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("CreateDelete"), - WithTopicTopicID(topicName), - WithTopicDeleted, + WithPubSubTopicPropagationPolicy("CreateDelete"), + WithPubSubTopicTopicID(topicName), + WithPubSubTopicDeleted, ), newSink(), newSecret(), @@ -556,16 +556,16 @@ func TestAllCases(t *testing.T) { }, { Name: "fail to delete - policy CreateDelete", Objects: []runtime.Object{ - NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, }), - WithTopicPropagationPolicy("CreateDelete"), - WithTopicTopicID(topicName), - WithTopicDeleted, + WithPubSubTopicPropagationPolicy("CreateDelete"), + WithPubSubTopicTopicID(topicName), + WithPubSubTopicDeleted, ), newSink(), newSecret(), @@ -689,9 +689,9 @@ func makeFalseStatusPublisher(reason, message string) *servingv1.Service { } func newPublisher() *servingv1.Service { - topic := NewTopic(topicName, testNS, - WithTopicUID(topicUID), - WithTopicSpec(pubsubv1alpha1.TopicSpec{ + topic := NewPubSubTopic(topicName, testNS, + WithPubSubTopicUID(topicUID), + WithPubSubTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, Topic: testTopicID, Secret: &secret, diff --git a/pkg/reconciler/testing/pullsubscription.go b/pkg/reconciler/testing/pubsub_pullsubscription.go similarity index 54% rename from pkg/reconciler/testing/pullsubscription.go rename to pkg/reconciler/testing/pubsub_pullsubscription.go index 0ac7ef7f48..3772f4878a 100644 --- a/pkg/reconciler/testing/pullsubscription.go +++ b/pkg/reconciler/testing/pubsub_pullsubscription.go @@ -30,11 +30,11 @@ import ( "github.com/google/knative-gcp/pkg/apis/pubsub/v1alpha1" ) -// PullSubscriptionOption enables further configuration of a PullSubscription. -type PullSubscriptionOption func(*v1alpha1.PullSubscription) +// PubSubPullSubscriptionOption enables further configuration of a PullSubscription. +type PubSubPullSubscriptionOption func(*v1alpha1.PullSubscription) -// NewPullSubscription creates a PullSubscription with PullSubscriptionOptions -func NewPullSubscription(name, namespace string, so ...PullSubscriptionOption) *v1alpha1.PullSubscription { +// NewPubSubPullSubscription creates a PullSubscription with PullSubscriptionOptions +func NewPubSubPullSubscription(name, namespace string, so ...PubSubPullSubscriptionOption) *v1alpha1.PullSubscription { s := &v1alpha1.PullSubscription{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -48,9 +48,9 @@ func NewPullSubscription(name, namespace string, so ...PullSubscriptionOption) * return s } -// NewPullSubscriptionWithNoDefaults creates a PullSubscription with +// NewPubSubPullSubscriptionWithNoDefaults creates a PullSubscription with // PullSubscriptionOptions but does not set defaults. -func NewPullSubscriptionWithNoDefaults(name, namespace string, so ...PullSubscriptionOption) *v1alpha1.PullSubscription { +func NewPubSubPullSubscriptionWithNoDefaults(name, namespace string, so ...PubSubPullSubscriptionOption) *v1alpha1.PullSubscription { s := &v1alpha1.PullSubscription{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -63,38 +63,18 @@ func NewPullSubscriptionWithNoDefaults(name, namespace string, so ...PullSubscri return s } -// NewPullSubscriptionWithoutNamespace creates a PullSubscription with PullSubscriptionOptions but without a specific namespace -func NewPullSubscriptionWithoutNamespace(name string, so ...PullSubscriptionOption) *v1alpha1.PullSubscription { - s := &v1alpha1.PullSubscription{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - }, - } - for _, opt := range so { - opt(s) - } - s.SetDefaults(context.Background()) - return s -} - -func WithPullSubscriptionUID(uid types.UID) PullSubscriptionOption { +func WithPubSubPullSubscriptionUID(uid types.UID) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.UID = uid } } -func WithPullSubscriptionGenerateName(generateName string) PullSubscriptionOption { - return func(c *v1alpha1.PullSubscription) { - c.ObjectMeta.GenerateName = generateName - } -} - -// WithInitPullSubscriptionConditions initializes the PullSubscriptions's conditions. -func WithInitPullSubscriptionConditions(s *v1alpha1.PullSubscription) { +// WithPubSubInitPullSubscriptionConditions initializes the PullSubscriptions's conditions. +func WithPubSubInitPullSubscriptionConditions(s *v1alpha1.PullSubscription) { s.Status.InitializeConditions() } -func WithPullSubscriptionSink(gvk metav1.GroupVersionKind, name string) PullSubscriptionOption { +func WithPubSubPullSubscriptionSink(gvk metav1.GroupVersionKind, name string) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Spec.Sink = duckv1.Destination{ Ref: &duckv1.KReference{ @@ -106,7 +86,7 @@ func WithPullSubscriptionSink(gvk metav1.GroupVersionKind, name string) PullSubs } } -func WithPullSubscriptionTransformer(gvk metav1.GroupVersionKind, name string) PullSubscriptionOption { +func WithPubSubPullSubscriptionTransformer(gvk metav1.GroupVersionKind, name string) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Spec.Transformer = &duckv1.Destination{ Ref: &duckv1.KReference{ @@ -118,59 +98,59 @@ func WithPullSubscriptionTransformer(gvk metav1.GroupVersionKind, name string) P } } -func WithPullSubscriptionMarkSink(uri *apis.URL) PullSubscriptionOption { +func WithPubSubPullSubscriptionMarkSink(uri *apis.URL) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Status.MarkSink(uri) } } -func WithPullSubscriptionMarkTransformer(uri *apis.URL) PullSubscriptionOption { +func WithPubSubPullSubscriptionMarkTransformer(uri *apis.URL) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Status.MarkTransformer(uri) } } -func WithPullSubscriptionMarkNoTransformer(reason, message string) PullSubscriptionOption { +func WithPubSubPullSubscriptionMarkNoTransformer(reason, message string) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Status.MarkNoTransformer(reason, message) } } -func WithPullSubscriptionMarkSubscribed(subscriptionID string) PullSubscriptionOption { +func WithPubSubPullSubscriptionMarkSubscribed(subscriptionID string) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Status.MarkSubscribed(subscriptionID) } } -func WithPullSubscriptionSubscriptionID(subscriptionID string) PullSubscriptionOption { +func WithPubSubPullSubscriptionSubscriptionID(subscriptionID string) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Status.SubscriptionID = subscriptionID } } -func WithPullSubscriptionProjectID(projectID string) PullSubscriptionOption { +func WithPubSubPullSubscriptionProjectID(projectID string) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Status.ProjectID = projectID } } -func WithPullSubscriptionTransformerURI(uri *apis.URL) PullSubscriptionOption { +func WithPubSubPullSubscriptionTransformerURI(uri *apis.URL) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Status.TransformerURI = uri } } -func WithPullSubscriptionMarkNoSubscription(reason, message string) PullSubscriptionOption { +func WithPubSubPullSubscriptionMarkNoSubscription(reason, message string) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Status.MarkNoSubscription(reason, message) } } -func WithPullSubscriptionMarkDeployed(ps *v1alpha1.PullSubscription) { +func WithPubSubPullSubscriptionMarkDeployed(ps *v1alpha1.PullSubscription) { ps.Status.MarkDeployed() } -func WithPullSubscriptionSpec(spec v1alpha1.PullSubscriptionSpec) PullSubscriptionOption { +func WithPubSubPullSubscriptionSpec(spec v1alpha1.PullSubscriptionSpec) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Spec = spec s.Spec.SetDefaults(context.Background()) @@ -178,13 +158,13 @@ func WithPullSubscriptionSpec(spec v1alpha1.PullSubscriptionSpec) PullSubscripti } // Same as withPullSubscriptionSpec but does not set defaults -func WithPullSubscriptionSpecWithNoDefaults(spec v1alpha1.PullSubscriptionSpec) PullSubscriptionOption { +func WithPubSubPullSubscriptionSpecWithNoDefaults(spec v1alpha1.PullSubscriptionSpec) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Spec = spec } } -func WithPullSubscriptionReady(sink *apis.URL) PullSubscriptionOption { +func WithPubSubPullSubscriptionReady(sink *apis.URL) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Status.InitializeConditions() s.Status.MarkSink(sink) @@ -193,7 +173,7 @@ func WithPullSubscriptionReady(sink *apis.URL) PullSubscriptionOption { } } -func WithPullSubscriptionFailed() PullSubscriptionOption { +func WithPubSubPullSubscriptionFailed() PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Status.InitializeConditions() s.Status.MarkNoSink("InvalidSink", @@ -202,68 +182,55 @@ func WithPullSubscriptionFailed() PullSubscriptionOption { } } -func WithPullSubscriptionUnknown() PullSubscriptionOption { +func WithPubSubPullSubscriptionUnknown() PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Status.InitializeConditions() } } -func WithPullSubscriptionJobFailure(subscriptionID, reason, message string) PullSubscriptionOption { - return func(s *v1alpha1.PullSubscription) { - s.Status.SubscriptionID = subscriptionID - s.Status.MarkNoSubscription(reason, message) - } -} - -func WithPullSubscriptionSinkNotFound() PullSubscriptionOption { +func WithPubSubPullSubscriptionSinkNotFound() PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Status.MarkNoSink("InvalidSink", `failed to get ref &ObjectReference{Kind:Sink,Namespace:testnamespace,Name:sink,UID:,APIVersion:testing.cloud.google.com/v1alpha1,ResourceVersion:,FieldPath:,}: sinks.testing.cloud.google.com "sink" not found`) } } -func WithPullSubscriptionDeleted(s *v1alpha1.PullSubscription) { +func WithPubSubPullSubscriptionDeleted(s *v1alpha1.PullSubscription) { t := metav1.NewTime(time.Unix(1e9, 0)) s.ObjectMeta.SetDeletionTimestamp(&t) } -func WithPullSubscriptionOwnerReferences(ownerReferences []metav1.OwnerReference) PullSubscriptionOption { +func WithPubSubPullSubscriptionOwnerReferences(ownerReferences []metav1.OwnerReference) PubSubPullSubscriptionOption { return func(c *v1alpha1.PullSubscription) { c.ObjectMeta.OwnerReferences = ownerReferences } } -func WithPullSubscriptionLabels(labels map[string]string) PullSubscriptionOption { +func WithPubSubPullSubscriptionLabels(labels map[string]string) PubSubPullSubscriptionOption { return func(c *v1alpha1.PullSubscription) { c.ObjectMeta.Labels = labels } } -func WithPullSubscriptionAnnotations(annotations map[string]string) PullSubscriptionOption { +func WithPubSubPullSubscriptionAnnotations(annotations map[string]string) PubSubPullSubscriptionOption { return func(c *v1alpha1.PullSubscription) { c.ObjectMeta.Annotations = annotations } } -func WithPullSubscriptionFinalizers(finalizers ...string) PullSubscriptionOption { - return func(s *v1alpha1.PullSubscription) { - s.Finalizers = finalizers - } -} - -func WithPullSubscriptionStatusObservedGeneration(generation int64) PullSubscriptionOption { +func WithPubSubPullSubscriptionStatusObservedGeneration(generation int64) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Status.Status.ObservedGeneration = generation } } -func WithPullSubscriptionObjectMetaGeneration(generation int64) PullSubscriptionOption { +func WithPubSubPullSubscriptionObjectMetaGeneration(generation int64) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.ObjectMeta.Generation = generation } } -func WithPullSubscriptionReadyStatus(status corev1.ConditionStatus, reason, message string) PullSubscriptionOption { +func WithPubSubPullSubscriptionReadyStatus(status corev1.ConditionStatus, reason, message string) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Status.Conditions = []apis.Condition{{ Type: apis.ConditionReady, @@ -274,7 +241,7 @@ func WithPullSubscriptionReadyStatus(status corev1.ConditionStatus, reason, mess } } -func WithPullSubscriptionMode(mode v1alpha1.ModeType) PullSubscriptionOption { +func WithPubSubPullSubscriptionMode(mode v1alpha1.ModeType) PubSubPullSubscriptionOption { return func(s *v1alpha1.PullSubscription) { s.Spec.Mode = mode } diff --git a/pkg/reconciler/testing/topic.go b/pkg/reconciler/testing/pubsub_topic.go similarity index 59% rename from pkg/reconciler/testing/topic.go rename to pkg/reconciler/testing/pubsub_topic.go index d38bc549a8..36abf1d57b 100644 --- a/pkg/reconciler/testing/topic.go +++ b/pkg/reconciler/testing/pubsub_topic.go @@ -28,11 +28,11 @@ import ( "github.com/google/knative-gcp/pkg/apis/pubsub/v1alpha1" ) -// TopicOption enables further configuration of a Topic. -type TopicOption func(*v1alpha1.Topic) +// PubSubTopicOption enables further configuration of a Topic. +type PubSubTopicOption func(*v1alpha1.Topic) -// NewTopic creates a Topic with TopicOptions -func NewTopic(name, namespace string, so ...TopicOption) *v1alpha1.Topic { +// NewPubSubTopic creates a Topic with TopicOptions +func NewPubSubTopic(name, namespace string, so ...PubSubTopicOption) *v1alpha1.Topic { s := &v1alpha1.Topic{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -46,45 +46,31 @@ func NewTopic(name, namespace string, so ...TopicOption) *v1alpha1.Topic { return s } -func WithTopicUID(uid types.UID) TopicOption { +func WithPubSubTopicUID(uid types.UID) PubSubTopicOption { return func(s *v1alpha1.Topic) { s.UID = uid } } -// WithInitTopicConditions initializes the Topics's conditions. -func WithInitTopicConditions(s *v1alpha1.Topic) { +// WithPubSubInitTopicConditions initializes the Topics's conditions. +func WithPubSubInitTopicConditions(s *v1alpha1.Topic) { s.Status.InitializeConditions() } -func WithTopicTopicID(topicID string) TopicOption { +func WithPubSubTopicTopicID(topicID string) PubSubTopicOption { return func(s *v1alpha1.Topic) { s.Status.MarkTopicReady() s.Status.TopicID = topicID } } -func WithTopicPropagationPolicy(policy string) TopicOption { +func WithPubSubTopicPropagationPolicy(policy string) PubSubTopicOption { return func(s *v1alpha1.Topic) { s.Spec.PropagationPolicy = v1alpha1.PropagationPolicyType(policy) } } -func WithTopicTopicDeleted(topicID string) TopicOption { - return func(s *v1alpha1.Topic) { - s.Status.MarkNoTopic("Deleted", "Successfully deleted topic %q.", topicID) - s.Status.TopicID = "" - } -} - -func WithTopicJobFailure(topicID, reason, message string) TopicOption { - return func(s *v1alpha1.Topic) { - s.Status.TopicID = topicID - s.Status.MarkNoTopic(reason, message) - } -} - -func WithTopicAddress(uri string) TopicOption { +func WithPubSubTopicAddress(uri string) PubSubTopicOption { return func(s *v1alpha1.Topic) { if uri != "" { u, _ := apis.ParseURL(uri) @@ -95,41 +81,41 @@ func WithTopicAddress(uri string) TopicOption { } } -func WithTopicSpec(spec v1alpha1.TopicSpec) TopicOption { +func WithPubSubTopicSpec(spec v1alpha1.TopicSpec) PubSubTopicOption { return func(s *v1alpha1.Topic) { s.Spec = spec } } -func WithTopicPublisherDeployed(s *v1alpha1.Topic) { +func WithPubSubTopicPublisherDeployed(s *v1alpha1.Topic) { s.Status.MarkPublisherDeployed() } -func WithTopicPublisherNotDeployed(reason, message string) TopicOption { +func WithPubSubTopicPublisherNotDeployed(reason, message string) PubSubTopicOption { return func(t *v1alpha1.Topic) { t.Status.MarkPublisherNotDeployed(reason, message) } } -func WithTopicPublisherUnknown(reason, message string) TopicOption { +func WithPubSubTopicPublisherUnknown(reason, message string) PubSubTopicOption { return func(t *v1alpha1.Topic) { t.Status.MarkPublisherUnknown(reason, message) } } -func WithTopicPublisherNotConfigured() TopicOption { +func WithPubSubTopicPublisherNotConfigured() PubSubTopicOption { return func(t *v1alpha1.Topic) { t.Status.MarkPublisherNotConfigured() } } -func WithTopicProjectID(projectID string) TopicOption { +func WithPubSubTopicProjectID(projectID string) PubSubTopicOption { return func(s *v1alpha1.Topic) { s.Status.ProjectID = projectID } } -func WithTopicReady(topicID string) TopicOption { +func WithPubSubTopicReady(topicID string) PubSubTopicOption { return func(s *v1alpha1.Topic) { s.Status.InitializeConditions() s.Status.MarkPublisherDeployed() @@ -138,44 +124,38 @@ func WithTopicReady(topicID string) TopicOption { } } -func WithTopicFailed() TopicOption { +func WithPubSubTopicFailed() PubSubTopicOption { return func(s *v1alpha1.Topic) { s.Status.InitializeConditions() s.Status.MarkPublisherNotDeployed("PublisherStatus", "Publisher has no Ready type status") } } -func WithTopicUnknown() TopicOption { +func WithPubSubTopicUnknown() PubSubTopicOption { return func(s *v1alpha1.Topic) { s.Status.InitializeConditions() } } -func WithTopicDeleted(t *v1alpha1.Topic) { +func WithPubSubTopicDeleted(t *v1alpha1.Topic) { tt := metav1.NewTime(time.Unix(1e9, 0)) t.ObjectMeta.SetDeletionTimestamp(&tt) } -func WithTopicOwnerReferences(ownerReferences []metav1.OwnerReference) TopicOption { +func WithPubSubTopicOwnerReferences(ownerReferences []metav1.OwnerReference) PubSubTopicOption { return func(c *v1alpha1.Topic) { c.ObjectMeta.OwnerReferences = ownerReferences } } -func WithTopicLabels(labels map[string]string) TopicOption { +func WithPubSubTopicLabels(labels map[string]string) PubSubTopicOption { return func(c *v1alpha1.Topic) { c.ObjectMeta.Labels = labels } } -func WithTopicNoTopic(reason, message string) TopicOption { +func WithPubSubTopicNoTopic(reason, message string) PubSubTopicOption { return func(t *v1alpha1.Topic) { t.Status.MarkNoTopic(reason, message) } } - -func WithTopicFinalizers(finalizers ...string) TopicOption { - return func(s *v1alpha1.Topic) { - s.Finalizers = finalizers - } -} diff --git a/test/e2e/test_pullsubscription.go b/test/e2e/test_pullsubscription.go index 24c83310d5..cc41a31946 100644 --- a/test/e2e/test_pullsubscription.go +++ b/test/e2e/test_pullsubscription.go @@ -46,8 +46,8 @@ func SmokePullSubscriptionTestImpl(t *testing.T, authConfig lib.AuthConfig) { defer lib.TearDown(client) // Create PullSubscription. - pullsubscription := kngcptesting.NewPullSubscription(psName, client.Namespace, - kngcptesting.WithPullSubscriptionSpec(v1alpha1.PullSubscriptionSpec{ + pullsubscription := kngcptesting.NewPubSubPullSubscription(psName, client.Namespace, + kngcptesting.WithPubSubPullSubscriptionSpec(v1alpha1.PullSubscriptionSpec{ Topic: topic, PubSubSpec: duckv1alpha1.PubSubSpec{ IdentitySpec: duckv1alpha1.IdentitySpec{ @@ -55,7 +55,7 @@ func SmokePullSubscriptionTestImpl(t *testing.T, authConfig lib.AuthConfig) { }, }, }), - kngcptesting.WithPullSubscriptionSink(lib.ServiceGVK, svcName)) + kngcptesting.WithPubSubPullSubscriptionSink(lib.ServiceGVK, svcName)) client.CreatePullSubscriptionOrFail(pullsubscription) client.Core.WaitForResourceReadyOrFail(psName, lib.PullSubscriptionTypeMeta) @@ -80,15 +80,15 @@ func PullSubscriptionWithTargetTestImpl(t *testing.T, authConfig lib.AuthConfig) client.CreateJobOrFail(job, lib.WithServiceForJob(targetName)) // Create PullSubscription. - pullsubscription := kngcptesting.NewPullSubscription(psName, client.Namespace, - kngcptesting.WithPullSubscriptionSpec(v1alpha1.PullSubscriptionSpec{ + pullsubscription := kngcptesting.NewPubSubPullSubscription(psName, client.Namespace, + kngcptesting.WithPubSubPullSubscriptionSpec(v1alpha1.PullSubscriptionSpec{ Topic: topicName, PubSubSpec: duckv1alpha1.PubSubSpec{ IdentitySpec: duckv1alpha1.IdentitySpec{ authConfig.PubsubServiceAccount, }, }, - }), kngcptesting.WithPullSubscriptionSink(lib.ServiceGVK, targetName)) + }), kngcptesting.WithPubSubPullSubscriptionSink(lib.ServiceGVK, targetName)) client.CreatePullSubscriptionOrFail(pullsubscription) client.Core.WaitForResourceReadyOrFail(psName, lib.PullSubscriptionTypeMeta) From b3eec6e092b76c2a4841a087889ca083ec8e8afb Mon Sep 17 00:00:00 2001 From: Adam Harwayne Date: Fri, 1 May 2020 17:19:11 -0700 Subject: [PATCH 3/7] Listers too. --- pkg/reconciler/events/build/build_test.go | 2 +- pkg/reconciler/events/pubsub/pubsub_test.go | 2 +- pkg/reconciler/messaging/channel/channel_test.go | 4 ++-- .../pubsub/pullsubscription/keda/pullsubscription_test.go | 4 ++-- .../pubsub/pullsubscription/static/pullsubscription_test.go | 4 ++-- pkg/reconciler/pubsub/topic/topic_test.go | 4 ++-- pkg/reconciler/testing/listers.go | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pkg/reconciler/events/build/build_test.go b/pkg/reconciler/events/build/build_test.go index 851f6ff6b3..7d36e23255 100644 --- a/pkg/reconciler/events/build/build_test.go +++ b/pkg/reconciler/events/build/build_test.go @@ -342,7 +342,7 @@ func TestAllCases(t *testing.T) { PubSubBase: pubsub.NewPubSubBase(ctx, controllerAgentName, receiveAdapterName, cmw), Identity: identity.NewIdentity(ctx, NoopIAMPolicyManager), buildLister: listers.GetCloudBuildSourceLister(), - pullsubscriptionLister: listers.GetPullSubscriptionLister(), + pullsubscriptionLister: listers.GetPubSubPullSubscriptionLister(), serviceAccountLister: listers.GetServiceAccountLister(), } return cloudbuildsource.NewReconciler(ctx, r.Logger, r.RunClientSet, listers.GetCloudBuildSourceLister(), r.Recorder, r) diff --git a/pkg/reconciler/events/pubsub/pubsub_test.go b/pkg/reconciler/events/pubsub/pubsub_test.go index cc937d47b6..061e4b08f0 100644 --- a/pkg/reconciler/events/pubsub/pubsub_test.go +++ b/pkg/reconciler/events/pubsub/pubsub_test.go @@ -341,7 +341,7 @@ func TestAllCases(t *testing.T) { PubSubBase: pubsub.NewPubSubBase(ctx, controllerAgentName, receiveAdapterName, cmw), Identity: identity.NewIdentity(ctx, NoopIAMPolicyManager), pubsubLister: listers.GetCloudPubSubSourceLister(), - pullsubscriptionLister: listers.GetPullSubscriptionLister(), + pullsubscriptionLister: listers.GetPubSubPullSubscriptionLister(), serviceAccountLister: listers.GetServiceAccountLister(), } return cloudpubsubsource.NewReconciler(ctx, r.Logger, r.RunClientSet, listers.GetCloudPubSubSourceLister(), r.Recorder, r) diff --git a/pkg/reconciler/messaging/channel/channel_test.go b/pkg/reconciler/messaging/channel/channel_test.go index 702e09b290..6af85adc81 100644 --- a/pkg/reconciler/messaging/channel/channel_test.go +++ b/pkg/reconciler/messaging/channel/channel_test.go @@ -534,8 +534,8 @@ func TestAllCases(t *testing.T) { Base: reconciler.NewBase(ctx, controllerAgentName, cmw), Identity: identity.NewIdentity(ctx, NoopIAMPolicyManager), channelLister: listers.GetChannelLister(), - topicLister: listers.GetTopicLister(), - pullSubscriptionLister: listers.GetPullSubscriptionLister(), + topicLister: listers.GetPubSubTopicLister(), + pullSubscriptionLister: listers.GetPubSubPullSubscriptionLister(), serviceAccountLister: listers.GetServiceAccountLister(), } return channel.NewReconciler(ctx, r.Logger, r.RunClientSet, listers.GetChannelLister(), r.Recorder, r) diff --git a/pkg/reconciler/pubsub/pullsubscription/keda/pullsubscription_test.go b/pkg/reconciler/pubsub/pullsubscription/keda/pullsubscription_test.go index 28630bd86c..3679b89c38 100644 --- a/pkg/reconciler/pubsub/pullsubscription/keda/pullsubscription_test.go +++ b/pkg/reconciler/pubsub/pullsubscription/keda/pullsubscription_test.go @@ -797,7 +797,7 @@ func TestAllCases(t *testing.T) { Base: &psreconciler.Base{ PubSubBase: pubsubBase, DeploymentLister: listers.GetDeploymentLister(), - PullSubscriptionLister: listers.GetPullSubscriptionLister(), + PullSubscriptionLister: listers.GetPubSubPullSubscriptionLister(), UriResolver: resolver.NewURIResolver(ctx, func(types.NamespacedName) {}), ReceiveAdapterImage: testImage, CreateClientFn: gpubsub.TestClientCreator(testData["ps"]), @@ -808,7 +808,7 @@ func TestAllCases(t *testing.T) { r.ReconcileDataPlaneFn = r.ReconcileScaledObject r.scaledObjectTracker = duck.NewListableTracker(ctx, resource.Get, func(types.NamespacedName) {}, 0) r.discoveryFn = mockDiscoveryFunc - return pullsubscription.NewReconciler(ctx, r.Logger, r.RunClientSet, listers.GetPullSubscriptionLister(), r.Recorder, r) + return pullsubscription.NewReconciler(ctx, r.Logger, r.RunClientSet, listers.GetPubSubPullSubscriptionLister(), r.Recorder, r) })) } diff --git a/pkg/reconciler/pubsub/pullsubscription/static/pullsubscription_test.go b/pkg/reconciler/pubsub/pullsubscription/static/pullsubscription_test.go index 078b0d6534..39caa90db4 100644 --- a/pkg/reconciler/pubsub/pullsubscription/static/pullsubscription_test.go +++ b/pkg/reconciler/pubsub/pullsubscription/static/pullsubscription_test.go @@ -767,7 +767,7 @@ func TestAllCases(t *testing.T) { Base: &psreconciler.Base{ PubSubBase: pubsubBase, DeploymentLister: listers.GetDeploymentLister(), - PullSubscriptionLister: listers.GetPullSubscriptionLister(), + PullSubscriptionLister: listers.GetPubSubPullSubscriptionLister(), UriResolver: resolver.NewURIResolver(ctx, func(types.NamespacedName) {}), ReceiveAdapterImage: testImage, CreateClientFn: gpubsub.TestClientCreator(testData["ps"]), @@ -776,7 +776,7 @@ func TestAllCases(t *testing.T) { }, } r.ReconcileDataPlaneFn = r.ReconcileDeployment - return pullsubscription.NewReconciler(ctx, r.Logger, r.RunClientSet, listers.GetPullSubscriptionLister(), r.Recorder, r) + return pullsubscription.NewReconciler(ctx, r.Logger, r.RunClientSet, listers.GetPubSubPullSubscriptionLister(), r.Recorder, r) })) } diff --git a/pkg/reconciler/pubsub/topic/topic_test.go b/pkg/reconciler/pubsub/topic/topic_test.go index af99bbe86f..8a82542070 100644 --- a/pkg/reconciler/pubsub/topic/topic_test.go +++ b/pkg/reconciler/pubsub/topic/topic_test.go @@ -592,12 +592,12 @@ func TestAllCases(t *testing.T) { } r := &Reconciler{ PubSubBase: pubsubBase, - topicLister: listers.GetTopicLister(), + topicLister: listers.GetPubSubTopicLister(), serviceLister: listers.GetV1ServiceLister(), publisherImage: testImage, createClientFn: gpubsub.TestClientCreator(testData["topic"]), } - return topic.NewReconciler(ctx, r.Logger, r.RunClientSet, listers.GetTopicLister(), r.Recorder, r) + return topic.NewReconciler(ctx, r.Logger, r.RunClientSet, listers.GetPubSubTopicLister(), r.Recorder, r) })) } diff --git a/pkg/reconciler/testing/listers.go b/pkg/reconciler/testing/listers.go index 29324df038..ae36a25d28 100644 --- a/pkg/reconciler/testing/listers.go +++ b/pkg/reconciler/testing/listers.go @@ -125,11 +125,11 @@ func (l *Listers) GetIstioObjects() []runtime.Object { return l.sorter.ObjectsForSchemeFunc(fakeistioclientset.AddToScheme) } -func (l *Listers) GetPullSubscriptionLister() pubsublisters.PullSubscriptionLister { +func (l *Listers) GetPubSubPullSubscriptionLister() pubsublisters.PullSubscriptionLister { return pubsublisters.NewPullSubscriptionLister(l.indexerFor(&pubsubv1alpha1.PullSubscription{})) } -func (l *Listers) GetTopicLister() pubsublisters.TopicLister { +func (l *Listers) GetPubSubTopicLister() pubsublisters.TopicLister { return pubsublisters.NewTopicLister(l.indexerFor(&pubsubv1alpha1.Topic{})) } From 1fb95fd73b0ba7e1f4159d2420d2e1cf1759e9ac Mon Sep 17 00:00:00 2001 From: Adam Harwayne Date: Fri, 1 May 2020 17:18:10 -0700 Subject: [PATCH 4/7] Add the testing methods. --- .../pullsubscription/resources/labels.go | 2 +- .../intevents/topic/resources/labels.go | 4 +- pkg/reconciler/testing/listers.go | 10 + pkg/reconciler/testing/pullsubscription.go | 281 ++++++++++++++++++ pkg/reconciler/testing/topic.go | 181 +++++++++++ 5 files changed, 475 insertions(+), 3 deletions(-) create mode 100644 pkg/reconciler/testing/pullsubscription.go create mode 100644 pkg/reconciler/testing/topic.go diff --git a/pkg/reconciler/intevents/pullsubscription/resources/labels.go b/pkg/reconciler/intevents/pullsubscription/resources/labels.go index 0e6db41fdf..141549f50f 100644 --- a/pkg/reconciler/intevents/pullsubscription/resources/labels.go +++ b/pkg/reconciler/intevents/pullsubscription/resources/labels.go @@ -26,7 +26,7 @@ func GetLabelSelector(controller, source string) labels.Selector { func GetLabels(controller, source string) map[string]string { return map[string]string{ - "events.cloud.google.com/controller": controller, + "internal.events.cloud.google.com/controller": controller, "internal.events.cloud.google.com/pullsubscription": source, } } diff --git a/pkg/reconciler/intevents/topic/resources/labels.go b/pkg/reconciler/intevents/topic/resources/labels.go index 8bf4d3ac2c..474e4b07c2 100644 --- a/pkg/reconciler/intevents/topic/resources/labels.go +++ b/pkg/reconciler/intevents/topic/resources/labels.go @@ -26,7 +26,7 @@ func GetLabelSelector(controller, source string) labels.Selector { func GetLabels(controller, topic string) map[string]string { return map[string]string{ - "internal.events.google.com/controller": controller, - "internal.events.google.com/topic": topic, + "internal.events.cloud.google.com/controller": controller, + "internal.events.cloud.google.com/topic": topic, } } diff --git a/pkg/reconciler/testing/listers.go b/pkg/reconciler/testing/listers.go index ae36a25d28..117ec5708e 100644 --- a/pkg/reconciler/testing/listers.go +++ b/pkg/reconciler/testing/listers.go @@ -43,6 +43,7 @@ import ( brokerv1beta1 "github.com/google/knative-gcp/pkg/apis/broker/v1beta1" EventsV1alpha1 "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" + inteventsv1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" intv1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" MessagingV1alpha1 "github.com/google/knative-gcp/pkg/apis/messaging/v1alpha1" policyv1alpha1 "github.com/google/knative-gcp/pkg/apis/policy/v1alpha1" @@ -50,6 +51,7 @@ import ( fakeeventsclientset "github.com/google/knative-gcp/pkg/client/clientset/versioned/fake" brokerlisters "github.com/google/knative-gcp/pkg/client/listers/broker/v1beta1" eventslisters "github.com/google/knative-gcp/pkg/client/listers/events/v1alpha1" + inteventslisters "github.com/google/knative-gcp/pkg/client/listers/intevents/v1alpha1" intlisters "github.com/google/knative-gcp/pkg/client/listers/intevents/v1alpha1" messaginglisters "github.com/google/knative-gcp/pkg/client/listers/messaging/v1alpha1" policylisters "github.com/google/knative-gcp/pkg/client/listers/policy/v1alpha1" @@ -125,6 +127,14 @@ func (l *Listers) GetIstioObjects() []runtime.Object { return l.sorter.ObjectsForSchemeFunc(fakeistioclientset.AddToScheme) } +func (l *Listers) GetPullSubscriptionLister() inteventslisters.PullSubscriptionLister { + return inteventslisters.NewPullSubscriptionLister(l.indexerFor(&inteventsv1alpha1.PullSubscription{})) +} + +func (l *Listers) GetTopicLister() inteventslisters.TopicLister { + return inteventslisters.NewTopicLister(l.indexerFor(&inteventsv1alpha1.Topic{})) +} + func (l *Listers) GetPubSubPullSubscriptionLister() pubsublisters.PullSubscriptionLister { return pubsublisters.NewPullSubscriptionLister(l.indexerFor(&pubsubv1alpha1.PullSubscription{})) } diff --git a/pkg/reconciler/testing/pullsubscription.go b/pkg/reconciler/testing/pullsubscription.go new file mode 100644 index 0000000000..2bc983a954 --- /dev/null +++ b/pkg/reconciler/testing/pullsubscription.go @@ -0,0 +1,281 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package testing + +import ( + "context" + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" + + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" +) + +// PullSubscriptionOption enables further configuration of a PullSubscription. +type PullSubscriptionOption func(*v1alpha1.PullSubscription) + +// NewPullSubscription creates a PullSubscription with PullSubscriptionOptions +func NewPullSubscription(name, namespace string, so ...PullSubscriptionOption) *v1alpha1.PullSubscription { + s := &v1alpha1.PullSubscription{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + } + for _, opt := range so { + opt(s) + } + s.SetDefaults(context.Background()) + return s +} + +// NewPullSubscriptionWithNoDefaults creates a PullSubscription with +// PullSubscriptionOptions but does not set defaults. +func NewPullSubscriptionWithNoDefaults(name, namespace string, so ...PullSubscriptionOption) *v1alpha1.PullSubscription { + s := &v1alpha1.PullSubscription{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + } + for _, opt := range so { + opt(s) + } + return s +} + +// NewPullSubscriptionWithoutNamespace creates a PullSubscription with PullSubscriptionOptions but without a specific namespace +func NewPullSubscriptionWithoutNamespace(name string, so ...PullSubscriptionOption) *v1alpha1.PullSubscription { + s := &v1alpha1.PullSubscription{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + } + for _, opt := range so { + opt(s) + } + s.SetDefaults(context.Background()) + return s +} + +func WithPullSubscriptionUID(uid types.UID) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.UID = uid + } +} + +func WithPullSubscriptionGenerateName(generateName string) PullSubscriptionOption { + return func(c *v1alpha1.PullSubscription) { + c.ObjectMeta.GenerateName = generateName + } +} + +// WithInitPullSubscriptionConditions initializes the PullSubscriptions's conditions. +func WithInitPullSubscriptionConditions(s *v1alpha1.PullSubscription) { + s.Status.InitializeConditions() +} + +func WithPullSubscriptionSink(gvk metav1.GroupVersionKind, name string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Spec.Sink = duckv1.Destination{ + Ref: &duckv1.KReference{ + APIVersion: apiVersion(gvk), + Kind: gvk.Kind, + Name: name, + }, + } + } +} + +func WithPullSubscriptionTransformer(gvk metav1.GroupVersionKind, name string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Spec.Transformer = &duckv1.Destination{ + Ref: &duckv1.KReference{ + APIVersion: apiVersion(gvk), + Kind: gvk.Kind, + Name: name, + }, + } + } +} + +func WithPullSubscriptionMarkSink(uri *apis.URL) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.MarkSink(uri) + } +} + +func WithPullSubscriptionMarkTransformer(uri *apis.URL) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.MarkTransformer(uri) + } +} + +func WithPullSubscriptionMarkNoTransformer(reason, message string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.MarkNoTransformer(reason, message) + } +} + +func WithPullSubscriptionMarkSubscribed(subscriptionID string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.MarkSubscribed(subscriptionID) + } +} + +func WithPullSubscriptionSubscriptionID(subscriptionID string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.SubscriptionID = subscriptionID + } +} + +func WithPullSubscriptionProjectID(projectID string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.ProjectID = projectID + } +} + +func WithPullSubscriptionTransformerURI(uri *apis.URL) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.TransformerURI = uri + } +} + +func WithPullSubscriptionMarkNoSubscription(reason, message string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.MarkNoSubscription(reason, message) + } +} + +func WithPullSubscriptionMarkDeployed(ps *v1alpha1.PullSubscription) { + ps.Status.MarkDeployed() +} + +func WithPullSubscriptionSpec(spec v1alpha1.PullSubscriptionSpec) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Spec = spec + s.Spec.SetDefaults(context.Background()) + } +} + +// Same as withPullSubscriptionSpec but does not set defaults +func WithPullSubscriptionSpecWithNoDefaults(spec v1alpha1.PullSubscriptionSpec) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Spec = spec + } +} + +func WithPullSubscriptionReady(sink *apis.URL) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.InitializeConditions() + s.Status.MarkSink(sink) + s.Status.MarkDeployed() + s.Status.MarkSubscribed("subID") + } +} + +func WithPullSubscriptionFailed() PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.InitializeConditions() + s.Status.MarkNoSink("InvalidSink", + `failed to get ref &ObjectReference{Kind:Sink,Namespace:testnamespace,Name:sink,UID:,APIVersion:testing.cloud.google.com/v1alpha1,ResourceVersion:,FieldPath:,}: sinks.testing.cloud.google.com "sink" not found`) + + } +} + +func WithPullSubscriptionUnknown() PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.InitializeConditions() + } +} + +func WithPullSubscriptionJobFailure(subscriptionID, reason, message string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.SubscriptionID = subscriptionID + s.Status.MarkNoSubscription(reason, message) + } +} + +func WithPullSubscriptionSinkNotFound() PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.MarkNoSink("InvalidSink", + `failed to get ref &ObjectReference{Kind:Sink,Namespace:testnamespace,Name:sink,UID:,APIVersion:testing.cloud.google.com/v1alpha1,ResourceVersion:,FieldPath:,}: sinks.testing.cloud.google.com "sink" not found`) + } +} + +func WithPullSubscriptionDeleted(s *v1alpha1.PullSubscription) { + t := metav1.NewTime(time.Unix(1e9, 0)) + s.ObjectMeta.SetDeletionTimestamp(&t) +} + +func WithPullSubscriptionOwnerReferences(ownerReferences []metav1.OwnerReference) PullSubscriptionOption { + return func(c *v1alpha1.PullSubscription) { + c.ObjectMeta.OwnerReferences = ownerReferences + } +} + +func WithPullSubscriptionLabels(labels map[string]string) PullSubscriptionOption { + return func(c *v1alpha1.PullSubscription) { + c.ObjectMeta.Labels = labels + } +} + +func WithPullSubscriptionAnnotations(annotations map[string]string) PullSubscriptionOption { + return func(c *v1alpha1.PullSubscription) { + c.ObjectMeta.Annotations = annotations + } +} + +func WithPullSubscriptionFinalizers(finalizers ...string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Finalizers = finalizers + } +} + +func WithPullSubscriptionStatusObservedGeneration(generation int64) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.Status.ObservedGeneration = generation + } +} + +func WithPullSubscriptionObjectMetaGeneration(generation int64) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.ObjectMeta.Generation = generation + } +} + +func WithPullSubscriptionReadyStatus(status corev1.ConditionStatus, reason, message string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.Conditions = []apis.Condition{{ + Type: apis.ConditionReady, + Status: status, + Reason: reason, + Message: message, + }} + } +} + +func WithPullSubscriptionMode(mode v1alpha1.ModeType) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Spec.Mode = mode + } +} diff --git a/pkg/reconciler/testing/topic.go b/pkg/reconciler/testing/topic.go new file mode 100644 index 0000000000..8272c4085d --- /dev/null +++ b/pkg/reconciler/testing/topic.go @@ -0,0 +1,181 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package testing + +import ( + "context" + "time" + + "knative.dev/pkg/apis" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" +) + +// TopicOption enables further configuration of a Topic. +type TopicOption func(*v1alpha1.Topic) + +// NewTopic creates a Topic with TopicOptions +func NewTopic(name, namespace string, so ...TopicOption) *v1alpha1.Topic { + s := &v1alpha1.Topic{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + } + for _, opt := range so { + opt(s) + } + s.SetDefaults(context.Background()) + return s +} + +func WithTopicUID(uid types.UID) TopicOption { + return func(s *v1alpha1.Topic) { + s.UID = uid + } +} + +// WithInitTopicConditions initializes the Topics's conditions. +func WithInitTopicConditions(s *v1alpha1.Topic) { + s.Status.InitializeConditions() +} + +func WithTopicTopicID(topicID string) TopicOption { + return func(s *v1alpha1.Topic) { + s.Status.MarkTopicReady() + s.Status.TopicID = topicID + } +} + +func WithTopicPropagationPolicy(policy string) TopicOption { + return func(s *v1alpha1.Topic) { + s.Spec.PropagationPolicy = v1alpha1.PropagationPolicyType(policy) + } +} + +func WithTopicTopicDeleted(topicID string) TopicOption { + return func(s *v1alpha1.Topic) { + s.Status.MarkNoTopic("Deleted", "Successfully deleted topic %q.", topicID) + s.Status.TopicID = "" + } +} + +func WithTopicJobFailure(topicID, reason, message string) TopicOption { + return func(s *v1alpha1.Topic) { + s.Status.TopicID = topicID + s.Status.MarkNoTopic(reason, message) + } +} + +func WithTopicAddress(uri string) TopicOption { + return func(s *v1alpha1.Topic) { + if uri != "" { + u, _ := apis.ParseURL(uri) + s.Status.SetAddress(u) + } else { + s.Status.SetAddress(nil) + } + } +} + +func WithTopicSpec(spec v1alpha1.TopicSpec) TopicOption { + return func(s *v1alpha1.Topic) { + s.Spec = spec + } +} + +func WithTopicPublisherDeployed(s *v1alpha1.Topic) { + s.Status.MarkPublisherDeployed() +} + +func WithTopicPublisherNotDeployed(reason, message string) TopicOption { + return func(t *v1alpha1.Topic) { + t.Status.MarkPublisherNotDeployed(reason, message) + } +} + +func WithTopicPublisherUnknown(reason, message string) TopicOption { + return func(t *v1alpha1.Topic) { + t.Status.MarkPublisherUnknown(reason, message) + } +} + +func WithTopicPublisherNotConfigured() TopicOption { + return func(t *v1alpha1.Topic) { + t.Status.MarkPublisherNotConfigured() + } +} + +func WithTopicProjectID(projectID string) TopicOption { + return func(s *v1alpha1.Topic) { + s.Status.ProjectID = projectID + } +} + +func WithTopicReady(topicID string) TopicOption { + return func(s *v1alpha1.Topic) { + s.Status.InitializeConditions() + s.Status.MarkPublisherDeployed() + s.Status.MarkTopicReady() + s.Status.TopicID = topicID + } +} + +func WithTopicFailed() TopicOption { + return func(s *v1alpha1.Topic) { + s.Status.InitializeConditions() + s.Status.MarkPublisherNotDeployed("PublisherStatus", "Publisher has no Ready type status") + } +} + +func WithTopicUnknown() TopicOption { + return func(s *v1alpha1.Topic) { + s.Status.InitializeConditions() + } +} + +func WithTopicDeleted(t *v1alpha1.Topic) { + tt := metav1.NewTime(time.Unix(1e9, 0)) + t.ObjectMeta.SetDeletionTimestamp(&tt) +} + +func WithTopicOwnerReferences(ownerReferences []metav1.OwnerReference) TopicOption { + return func(c *v1alpha1.Topic) { + c.ObjectMeta.OwnerReferences = ownerReferences + } +} + +func WithTopicLabels(labels map[string]string) TopicOption { + return func(c *v1alpha1.Topic) { + c.ObjectMeta.Labels = labels + } +} + +func WithTopicNoTopic(reason, message string) TopicOption { + return func(t *v1alpha1.Topic) { + t.Status.MarkNoTopic(reason, message) + } +} + +func WithTopicFinalizers(finalizers ...string) TopicOption { + return func(s *v1alpha1.Topic) { + s.Finalizers = finalizers + } +} From e96971609e15f164390b2317247f4349e3cc6cd0 Mon Sep 17 00:00:00 2001 From: Adam Harwayne Date: Mon, 4 May 2020 13:07:51 -0700 Subject: [PATCH 5/7] Add to webhook. --- cmd/webhook/main.go | 26 ++++++++++++++++++++++++++ pkg/apis/intevents/register.go | 15 +++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/cmd/webhook/main.go b/cmd/webhook/main.go index 7f0bbac60e..8427aeadd5 100644 --- a/cmd/webhook/main.go +++ b/cmd/webhook/main.go @@ -23,6 +23,9 @@ import ( "github.com/google/knative-gcp/pkg/apis/events" eventsv1alpha1 "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" eventsv1beta1 "github.com/google/knative-gcp/pkg/apis/events/v1beta1" + "github.com/google/knative-gcp/pkg/apis/intevents" + inteventsv1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + inteventsv1beta1 "github.com/google/knative-gcp/pkg/apis/intevents/v1beta1" "github.com/google/knative-gcp/pkg/apis/messaging" messagingv1alpha1 "github.com/google/knative-gcp/pkg/apis/messaging/v1alpha1" messagingv1beta1 "github.com/google/knative-gcp/pkg/apis/messaging/v1beta1" @@ -58,6 +61,10 @@ var types = map[schema.GroupVersionKind]resourcesemantics.GenericCRD{ eventsv1alpha1.SchemeGroupVersion.WithKind("CloudAuditLogsSource"): &eventsv1alpha1.CloudAuditLogsSource{}, eventsv1alpha1.SchemeGroupVersion.WithKind("CloudBuildSource"): &eventsv1alpha1.CloudBuildSource{}, + // For group internal.events.cloud.google.com. + inteventsv1alpha1.SchemeGroupVersion.WithKind("PullSubscription"): &inteventsv1alpha1.PullSubscription{}, + inteventsv1alpha1.SchemeGroupVersion.WithKind("Topic"): &inteventsv1alpha1.Topic{}, + // For group pubsub.cloud.google.com. pubsubv1alpha1.SchemeGroupVersion.WithKind("PullSubscription"): &pubsubv1alpha1.PullSubscription{}, pubsubv1alpha1.SchemeGroupVersion.WithKind("Topic"): &pubsubv1alpha1.Topic{}, @@ -138,6 +145,8 @@ func NewConversionController(ctx context.Context, _ configmap.Watcher) *controll messagingv1beta1_ = messagingv1beta1.SchemeGroupVersion.Version pubsubv1alpha1_ = pubsubv1alpha1.SchemeGroupVersion.Version pubsubv1beta1_ = pubsubv1beta1.SchemeGroupVersion.Version + inteventsv1alpha1_ = inteventsv1alpha1.SchemeGroupVersion.Version + inteventsv1beta1_ = inteventsv1beta1.SchemeGroupVersion.Version ) return conversion.NewConversionController(ctx, @@ -179,6 +188,23 @@ func NewConversionController(ctx context.Context, _ configmap.Watcher) *controll eventsv1beta1_: &eventsv1beta1.CloudStorageSource{}, }, }, + // intevents + inteventsv1alpha1.Kind("PullSubscription"): { + DefinitionName: intevents.PullSubscriptionsResource.String(), + HubVersion: inteventsv1alpha1_, + Zygotes: map[string]conversion.ConvertibleObject{ + inteventsv1alpha1_: &inteventsv1alpha1.PullSubscription{}, + inteventsv1beta1_: &inteventsv1beta1.PullSubscription{}, + }, + }, + inteventsv1alpha1.Kind("Topic"): { + DefinitionName: intevents.TopicsResource.String(), + HubVersion: inteventsv1alpha1_, + Zygotes: map[string]conversion.ConvertibleObject{ + inteventsv1alpha1_: &inteventsv1alpha1.Topic{}, + inteventsv1beta1_: &inteventsv1beta1.Topic{}, + }, + }, // messaging messagingv1alpha1.Kind("Channel"): { DefinitionName: messaging.ChannelsResource.String(), diff --git a/pkg/apis/intevents/register.go b/pkg/apis/intevents/register.go index 029a1b8f04..625b4ae6bd 100644 --- a/pkg/apis/intevents/register.go +++ b/pkg/apis/intevents/register.go @@ -18,6 +18,21 @@ limitations under the License. // resources. package intevents +import "k8s.io/apimachinery/pkg/runtime/schema" + const ( GroupName = "internal.events.cloud.google.com" ) + +var ( + // PullSubscriptionsResource represents a PullSubscription. + PullSubscriptionsResource = schema.GroupResource{ + Group: GroupName, + Resource: "pullsubscriptions", + } + // TopicsResource represents a Topic. + TopicsResource = schema.GroupResource{ + Group: GroupName, + Resource: "topics", + } +) From e8c4a54944a5893268763873da681971dc73c308 Mon Sep 17 00:00:00 2001 From: Adam Harwayne Date: Wed, 6 May 2020 13:19:30 -0700 Subject: [PATCH 6/7] Add back the reconciler testing helpers, accidentally removed in a previous merge. --- pkg/reconciler/testing/pullsubscription.go | 281 +++++++++++++++++++++ pkg/reconciler/testing/topic.go | 181 +++++++++++++ 2 files changed, 462 insertions(+) create mode 100644 pkg/reconciler/testing/pullsubscription.go create mode 100644 pkg/reconciler/testing/topic.go diff --git a/pkg/reconciler/testing/pullsubscription.go b/pkg/reconciler/testing/pullsubscription.go new file mode 100644 index 0000000000..2bc983a954 --- /dev/null +++ b/pkg/reconciler/testing/pullsubscription.go @@ -0,0 +1,281 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package testing + +import ( + "context" + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" + + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" +) + +// PullSubscriptionOption enables further configuration of a PullSubscription. +type PullSubscriptionOption func(*v1alpha1.PullSubscription) + +// NewPullSubscription creates a PullSubscription with PullSubscriptionOptions +func NewPullSubscription(name, namespace string, so ...PullSubscriptionOption) *v1alpha1.PullSubscription { + s := &v1alpha1.PullSubscription{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + } + for _, opt := range so { + opt(s) + } + s.SetDefaults(context.Background()) + return s +} + +// NewPullSubscriptionWithNoDefaults creates a PullSubscription with +// PullSubscriptionOptions but does not set defaults. +func NewPullSubscriptionWithNoDefaults(name, namespace string, so ...PullSubscriptionOption) *v1alpha1.PullSubscription { + s := &v1alpha1.PullSubscription{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + } + for _, opt := range so { + opt(s) + } + return s +} + +// NewPullSubscriptionWithoutNamespace creates a PullSubscription with PullSubscriptionOptions but without a specific namespace +func NewPullSubscriptionWithoutNamespace(name string, so ...PullSubscriptionOption) *v1alpha1.PullSubscription { + s := &v1alpha1.PullSubscription{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + } + for _, opt := range so { + opt(s) + } + s.SetDefaults(context.Background()) + return s +} + +func WithPullSubscriptionUID(uid types.UID) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.UID = uid + } +} + +func WithPullSubscriptionGenerateName(generateName string) PullSubscriptionOption { + return func(c *v1alpha1.PullSubscription) { + c.ObjectMeta.GenerateName = generateName + } +} + +// WithInitPullSubscriptionConditions initializes the PullSubscriptions's conditions. +func WithInitPullSubscriptionConditions(s *v1alpha1.PullSubscription) { + s.Status.InitializeConditions() +} + +func WithPullSubscriptionSink(gvk metav1.GroupVersionKind, name string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Spec.Sink = duckv1.Destination{ + Ref: &duckv1.KReference{ + APIVersion: apiVersion(gvk), + Kind: gvk.Kind, + Name: name, + }, + } + } +} + +func WithPullSubscriptionTransformer(gvk metav1.GroupVersionKind, name string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Spec.Transformer = &duckv1.Destination{ + Ref: &duckv1.KReference{ + APIVersion: apiVersion(gvk), + Kind: gvk.Kind, + Name: name, + }, + } + } +} + +func WithPullSubscriptionMarkSink(uri *apis.URL) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.MarkSink(uri) + } +} + +func WithPullSubscriptionMarkTransformer(uri *apis.URL) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.MarkTransformer(uri) + } +} + +func WithPullSubscriptionMarkNoTransformer(reason, message string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.MarkNoTransformer(reason, message) + } +} + +func WithPullSubscriptionMarkSubscribed(subscriptionID string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.MarkSubscribed(subscriptionID) + } +} + +func WithPullSubscriptionSubscriptionID(subscriptionID string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.SubscriptionID = subscriptionID + } +} + +func WithPullSubscriptionProjectID(projectID string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.ProjectID = projectID + } +} + +func WithPullSubscriptionTransformerURI(uri *apis.URL) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.TransformerURI = uri + } +} + +func WithPullSubscriptionMarkNoSubscription(reason, message string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.MarkNoSubscription(reason, message) + } +} + +func WithPullSubscriptionMarkDeployed(ps *v1alpha1.PullSubscription) { + ps.Status.MarkDeployed() +} + +func WithPullSubscriptionSpec(spec v1alpha1.PullSubscriptionSpec) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Spec = spec + s.Spec.SetDefaults(context.Background()) + } +} + +// Same as withPullSubscriptionSpec but does not set defaults +func WithPullSubscriptionSpecWithNoDefaults(spec v1alpha1.PullSubscriptionSpec) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Spec = spec + } +} + +func WithPullSubscriptionReady(sink *apis.URL) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.InitializeConditions() + s.Status.MarkSink(sink) + s.Status.MarkDeployed() + s.Status.MarkSubscribed("subID") + } +} + +func WithPullSubscriptionFailed() PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.InitializeConditions() + s.Status.MarkNoSink("InvalidSink", + `failed to get ref &ObjectReference{Kind:Sink,Namespace:testnamespace,Name:sink,UID:,APIVersion:testing.cloud.google.com/v1alpha1,ResourceVersion:,FieldPath:,}: sinks.testing.cloud.google.com "sink" not found`) + + } +} + +func WithPullSubscriptionUnknown() PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.InitializeConditions() + } +} + +func WithPullSubscriptionJobFailure(subscriptionID, reason, message string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.SubscriptionID = subscriptionID + s.Status.MarkNoSubscription(reason, message) + } +} + +func WithPullSubscriptionSinkNotFound() PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.MarkNoSink("InvalidSink", + `failed to get ref &ObjectReference{Kind:Sink,Namespace:testnamespace,Name:sink,UID:,APIVersion:testing.cloud.google.com/v1alpha1,ResourceVersion:,FieldPath:,}: sinks.testing.cloud.google.com "sink" not found`) + } +} + +func WithPullSubscriptionDeleted(s *v1alpha1.PullSubscription) { + t := metav1.NewTime(time.Unix(1e9, 0)) + s.ObjectMeta.SetDeletionTimestamp(&t) +} + +func WithPullSubscriptionOwnerReferences(ownerReferences []metav1.OwnerReference) PullSubscriptionOption { + return func(c *v1alpha1.PullSubscription) { + c.ObjectMeta.OwnerReferences = ownerReferences + } +} + +func WithPullSubscriptionLabels(labels map[string]string) PullSubscriptionOption { + return func(c *v1alpha1.PullSubscription) { + c.ObjectMeta.Labels = labels + } +} + +func WithPullSubscriptionAnnotations(annotations map[string]string) PullSubscriptionOption { + return func(c *v1alpha1.PullSubscription) { + c.ObjectMeta.Annotations = annotations + } +} + +func WithPullSubscriptionFinalizers(finalizers ...string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Finalizers = finalizers + } +} + +func WithPullSubscriptionStatusObservedGeneration(generation int64) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.Status.ObservedGeneration = generation + } +} + +func WithPullSubscriptionObjectMetaGeneration(generation int64) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.ObjectMeta.Generation = generation + } +} + +func WithPullSubscriptionReadyStatus(status corev1.ConditionStatus, reason, message string) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Status.Conditions = []apis.Condition{{ + Type: apis.ConditionReady, + Status: status, + Reason: reason, + Message: message, + }} + } +} + +func WithPullSubscriptionMode(mode v1alpha1.ModeType) PullSubscriptionOption { + return func(s *v1alpha1.PullSubscription) { + s.Spec.Mode = mode + } +} diff --git a/pkg/reconciler/testing/topic.go b/pkg/reconciler/testing/topic.go new file mode 100644 index 0000000000..8272c4085d --- /dev/null +++ b/pkg/reconciler/testing/topic.go @@ -0,0 +1,181 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package testing + +import ( + "context" + "time" + + "knative.dev/pkg/apis" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" +) + +// TopicOption enables further configuration of a Topic. +type TopicOption func(*v1alpha1.Topic) + +// NewTopic creates a Topic with TopicOptions +func NewTopic(name, namespace string, so ...TopicOption) *v1alpha1.Topic { + s := &v1alpha1.Topic{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + } + for _, opt := range so { + opt(s) + } + s.SetDefaults(context.Background()) + return s +} + +func WithTopicUID(uid types.UID) TopicOption { + return func(s *v1alpha1.Topic) { + s.UID = uid + } +} + +// WithInitTopicConditions initializes the Topics's conditions. +func WithInitTopicConditions(s *v1alpha1.Topic) { + s.Status.InitializeConditions() +} + +func WithTopicTopicID(topicID string) TopicOption { + return func(s *v1alpha1.Topic) { + s.Status.MarkTopicReady() + s.Status.TopicID = topicID + } +} + +func WithTopicPropagationPolicy(policy string) TopicOption { + return func(s *v1alpha1.Topic) { + s.Spec.PropagationPolicy = v1alpha1.PropagationPolicyType(policy) + } +} + +func WithTopicTopicDeleted(topicID string) TopicOption { + return func(s *v1alpha1.Topic) { + s.Status.MarkNoTopic("Deleted", "Successfully deleted topic %q.", topicID) + s.Status.TopicID = "" + } +} + +func WithTopicJobFailure(topicID, reason, message string) TopicOption { + return func(s *v1alpha1.Topic) { + s.Status.TopicID = topicID + s.Status.MarkNoTopic(reason, message) + } +} + +func WithTopicAddress(uri string) TopicOption { + return func(s *v1alpha1.Topic) { + if uri != "" { + u, _ := apis.ParseURL(uri) + s.Status.SetAddress(u) + } else { + s.Status.SetAddress(nil) + } + } +} + +func WithTopicSpec(spec v1alpha1.TopicSpec) TopicOption { + return func(s *v1alpha1.Topic) { + s.Spec = spec + } +} + +func WithTopicPublisherDeployed(s *v1alpha1.Topic) { + s.Status.MarkPublisherDeployed() +} + +func WithTopicPublisherNotDeployed(reason, message string) TopicOption { + return func(t *v1alpha1.Topic) { + t.Status.MarkPublisherNotDeployed(reason, message) + } +} + +func WithTopicPublisherUnknown(reason, message string) TopicOption { + return func(t *v1alpha1.Topic) { + t.Status.MarkPublisherUnknown(reason, message) + } +} + +func WithTopicPublisherNotConfigured() TopicOption { + return func(t *v1alpha1.Topic) { + t.Status.MarkPublisherNotConfigured() + } +} + +func WithTopicProjectID(projectID string) TopicOption { + return func(s *v1alpha1.Topic) { + s.Status.ProjectID = projectID + } +} + +func WithTopicReady(topicID string) TopicOption { + return func(s *v1alpha1.Topic) { + s.Status.InitializeConditions() + s.Status.MarkPublisherDeployed() + s.Status.MarkTopicReady() + s.Status.TopicID = topicID + } +} + +func WithTopicFailed() TopicOption { + return func(s *v1alpha1.Topic) { + s.Status.InitializeConditions() + s.Status.MarkPublisherNotDeployed("PublisherStatus", "Publisher has no Ready type status") + } +} + +func WithTopicUnknown() TopicOption { + return func(s *v1alpha1.Topic) { + s.Status.InitializeConditions() + } +} + +func WithTopicDeleted(t *v1alpha1.Topic) { + tt := metav1.NewTime(time.Unix(1e9, 0)) + t.ObjectMeta.SetDeletionTimestamp(&tt) +} + +func WithTopicOwnerReferences(ownerReferences []metav1.OwnerReference) TopicOption { + return func(c *v1alpha1.Topic) { + c.ObjectMeta.OwnerReferences = ownerReferences + } +} + +func WithTopicLabels(labels map[string]string) TopicOption { + return func(c *v1alpha1.Topic) { + c.ObjectMeta.Labels = labels + } +} + +func WithTopicNoTopic(reason, message string) TopicOption { + return func(t *v1alpha1.Topic) { + t.Status.MarkNoTopic(reason, message) + } +} + +func WithTopicFinalizers(finalizers ...string) TopicOption { + return func(s *v1alpha1.Topic) { + s.Finalizers = finalizers + } +} From f237cbffd58e0c49df8b920dad2493099b4f0c3f Mon Sep 17 00:00:00 2001 From: Adam Harwayne Date: Mon, 11 May 2020 10:37:46 -0700 Subject: [PATCH 7/7] Copy over the generic pubsub reconciler. --- pkg/reconciler/intevents/controller.go | 43 ++ pkg/reconciler/intevents/controller_test.go | 36 + .../pullsubscription/keda/controller.go | 4 +- .../keda/pullsubscription_test.go | 4 +- .../intevents/pullsubscription/reconciler.go | 4 +- .../pullsubscription/static/controller.go | 4 +- .../static/pullsubscription_test.go | 4 +- pkg/reconciler/intevents/reconciler.go | 252 +++++++ pkg/reconciler/intevents/reconciler_test.go | 686 ++++++++++++++++++ .../intevents/resources/annotations.go | 26 + pkg/reconciler/intevents/resources/labels.go | 24 + .../intevents/resources/labels_test.go | 35 + .../intevents/resources/pullsubscription.go | 73 ++ .../resources/pullsubscription_test.go | 133 ++++ pkg/reconciler/intevents/resources/topic.go | 56 ++ .../intevents/resources/topic_test.go | 185 +++++ pkg/reconciler/intevents/topic/controller.go | 4 +- pkg/reconciler/intevents/topic/topic.go | 4 +- pkg/reconciler/intevents/topic/topic_test.go | 8 +- 19 files changed, 1567 insertions(+), 18 deletions(-) create mode 100644 pkg/reconciler/intevents/controller.go create mode 100644 pkg/reconciler/intevents/controller_test.go create mode 100644 pkg/reconciler/intevents/reconciler.go create mode 100644 pkg/reconciler/intevents/reconciler_test.go create mode 100644 pkg/reconciler/intevents/resources/annotations.go create mode 100644 pkg/reconciler/intevents/resources/labels.go create mode 100644 pkg/reconciler/intevents/resources/labels_test.go create mode 100644 pkg/reconciler/intevents/resources/pullsubscription.go create mode 100644 pkg/reconciler/intevents/resources/pullsubscription_test.go create mode 100644 pkg/reconciler/intevents/resources/topic.go create mode 100644 pkg/reconciler/intevents/resources/topic_test.go diff --git a/pkg/reconciler/intevents/controller.go b/pkg/reconciler/intevents/controller.go new file mode 100644 index 0000000000..993fe3f01e --- /dev/null +++ b/pkg/reconciler/intevents/controller.go @@ -0,0 +1,43 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package intevents + +import ( + "context" + + "knative.dev/pkg/configmap" + + pubsubClient "github.com/google/knative-gcp/pkg/client/injection/client" + "github.com/google/knative-gcp/pkg/reconciler" +) + +func NewPubSubBase(ctx context.Context, controllerAgentName, receiveAdapterName string, cmw configmap.Watcher) *PubSubBase { + return &PubSubBase{ + Base: reconciler.NewBase(ctx, controllerAgentName, cmw), + pubsubClient: pubsubClient.Get(ctx), + receiveAdapterName: receiveAdapterName, + } +} + +func NewPubSubBaseWithAdapter(ctx context.Context, controllerAgentName, receiveAdapterName string, adapterType string, cmw configmap.Watcher) *PubSubBase { + return &PubSubBase{ + Base: reconciler.NewBase(ctx, controllerAgentName, cmw), + pubsubClient: pubsubClient.Get(ctx), + receiveAdapterName: receiveAdapterName, + adapterType: adapterType, + } +} diff --git a/pkg/reconciler/intevents/controller_test.go b/pkg/reconciler/intevents/controller_test.go new file mode 100644 index 0000000000..98d7a14ce1 --- /dev/null +++ b/pkg/reconciler/intevents/controller_test.go @@ -0,0 +1,36 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package intevents + +import ( + "testing" + + "knative.dev/pkg/configmap" + logtesting "knative.dev/pkg/logging/testing" + . "knative.dev/pkg/reconciler/testing" +) + +func TestNew(t *testing.T) { + defer logtesting.ClearAll() + ctx, _ := SetupFakeContext(t) + + c := NewPubSubBase(ctx, "test-controller", "test-ra", configmap.NewStaticWatcher()) + + if c == nil { + t.Fatal("Expected NewPubSubBase to return a non-nil value") + } +} diff --git a/pkg/reconciler/intevents/pullsubscription/keda/controller.go b/pkg/reconciler/intevents/pullsubscription/keda/controller.go index 6ce54ac748..760676bf0a 100644 --- a/pkg/reconciler/intevents/pullsubscription/keda/controller.go +++ b/pkg/reconciler/intevents/pullsubscription/keda/controller.go @@ -32,8 +32,8 @@ import ( "github.com/google/knative-gcp/pkg/reconciler" "github.com/google/knative-gcp/pkg/reconciler/identity" "github.com/google/knative-gcp/pkg/reconciler/identity/iam" + "github.com/google/knative-gcp/pkg/reconciler/intevents" psreconciler "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription" - "github.com/google/knative-gcp/pkg/reconciler/pubsub" "github.com/kelseyhightower/envconfig" eventingduck "knative.dev/eventing/pkg/duck" @@ -92,7 +92,7 @@ func newControllerWithIAMPolicyManager( logger.Fatal("Failed to process env var", zap.Error(err)) } - pubsubBase := &pubsub.PubSubBase{ + pubsubBase := &intevents.PubSubBase{ Base: reconciler.NewBase(ctx, controllerAgentName, cmw), } diff --git a/pkg/reconciler/intevents/pullsubscription/keda/pullsubscription_test.go b/pkg/reconciler/intevents/pullsubscription/keda/pullsubscription_test.go index d00273a7e6..12b3ca1541 100644 --- a/pkg/reconciler/intevents/pullsubscription/keda/pullsubscription_test.go +++ b/pkg/reconciler/intevents/pullsubscription/keda/pullsubscription_test.go @@ -51,10 +51,10 @@ import ( "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription" gpubsub "github.com/google/knative-gcp/pkg/gclient/pubsub/testing" "github.com/google/knative-gcp/pkg/reconciler" + "github.com/google/knative-gcp/pkg/reconciler/intevents" psreconciler "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription" . "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription/keda/resources" "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription/resources" - "github.com/google/knative-gcp/pkg/reconciler/pubsub" . "github.com/google/knative-gcp/pkg/reconciler/testing" "knative.dev/eventing/pkg/duck" ) @@ -790,7 +790,7 @@ func TestAllCases(t *testing.T) { table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher, testData map[string]interface{}) controller.Reconciler { ctx = addressable.WithDuck(ctx) ctx = resource.WithDuck(ctx) - pubsubBase := &pubsub.PubSubBase{ + pubsubBase := &intevents.PubSubBase{ Base: reconciler.NewBase(ctx, controllerAgentName, cmw), } r := &Reconciler{ diff --git a/pkg/reconciler/intevents/pullsubscription/reconciler.go b/pkg/reconciler/intevents/pullsubscription/reconciler.go index f68912b083..40f38b3fa0 100644 --- a/pkg/reconciler/intevents/pullsubscription/reconciler.go +++ b/pkg/reconciler/intevents/pullsubscription/reconciler.go @@ -44,8 +44,8 @@ import ( listers "github.com/google/knative-gcp/pkg/client/listers/intevents/v1alpha1" gpubsub "github.com/google/knative-gcp/pkg/gclient/pubsub" "github.com/google/knative-gcp/pkg/reconciler/identity" + "github.com/google/knative-gcp/pkg/reconciler/intevents" "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription/resources" - "github.com/google/knative-gcp/pkg/reconciler/pubsub" "github.com/google/knative-gcp/pkg/tracing" ) @@ -64,7 +64,7 @@ const ( // Base implements the core controller logic for pullsubscription. type Base struct { - *pubsub.PubSubBase + *intevents.PubSubBase // identity reconciler for reconciling workload identity. *identity.Identity // DeploymentLister index properties about deployments. diff --git a/pkg/reconciler/intevents/pullsubscription/static/controller.go b/pkg/reconciler/intevents/pullsubscription/static/controller.go index babbce5a7a..8e9a68f89c 100644 --- a/pkg/reconciler/intevents/pullsubscription/static/controller.go +++ b/pkg/reconciler/intevents/pullsubscription/static/controller.go @@ -26,8 +26,8 @@ import ( "github.com/google/knative-gcp/pkg/reconciler" "github.com/google/knative-gcp/pkg/reconciler/identity" "github.com/google/knative-gcp/pkg/reconciler/identity/iam" + "github.com/google/knative-gcp/pkg/reconciler/intevents" psreconciler "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription" - "github.com/google/knative-gcp/pkg/reconciler/pubsub" "github.com/kelseyhightower/envconfig" "go.uber.org/zap" "k8s.io/client-go/tools/cache" @@ -88,7 +88,7 @@ func newControllerWithIAMPolicyManager( logger.Fatal("Failed to process env var", zap.Error(err)) } - pubsubBase := &pubsub.PubSubBase{ + pubsubBase := &intevents.PubSubBase{ Base: reconciler.NewBase(ctx, controllerAgentName, cmw), } diff --git a/pkg/reconciler/intevents/pullsubscription/static/pullsubscription_test.go b/pkg/reconciler/intevents/pullsubscription/static/pullsubscription_test.go index a33fba3bcd..8f3cf16b89 100644 --- a/pkg/reconciler/intevents/pullsubscription/static/pullsubscription_test.go +++ b/pkg/reconciler/intevents/pullsubscription/static/pullsubscription_test.go @@ -47,9 +47,9 @@ import ( "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription" gpubsub "github.com/google/knative-gcp/pkg/gclient/pubsub/testing" "github.com/google/knative-gcp/pkg/reconciler" + "github.com/google/knative-gcp/pkg/reconciler/intevents" psreconciler "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription" "github.com/google/knative-gcp/pkg/reconciler/intevents/pullsubscription/resources" - "github.com/google/knative-gcp/pkg/reconciler/pubsub" . "github.com/google/knative-gcp/pkg/reconciler/testing" ) @@ -760,7 +760,7 @@ func TestAllCases(t *testing.T) { defer logtesting.ClearAll() table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher, testData map[string]interface{}) controller.Reconciler { ctx = addressable.WithDuck(ctx) - pubsubBase := &pubsub.PubSubBase{ + pubsubBase := &intevents.PubSubBase{ Base: reconciler.NewBase(ctx, controllerAgentName, cmw), } r := &Reconciler{ diff --git a/pkg/reconciler/intevents/reconciler.go b/pkg/reconciler/intevents/reconciler.go new file mode 100644 index 0000000000..0b1082c0b8 --- /dev/null +++ b/pkg/reconciler/intevents/reconciler.go @@ -0,0 +1,252 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package intevents + +import ( + "context" + "fmt" + + duckv1alpha1 "github.com/google/knative-gcp/pkg/apis/duck/v1alpha1" + inteventsv1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + clientset "github.com/google/knative-gcp/pkg/client/clientset/versioned" + duck "github.com/google/knative-gcp/pkg/duck/v1alpha1" + "github.com/google/knative-gcp/pkg/reconciler" + "github.com/google/knative-gcp/pkg/reconciler/intevents/resources" + "go.uber.org/zap" + corev1 "k8s.io/api/core/v1" + apierrs "k8s.io/apimachinery/pkg/api/errors" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/apis" + "knative.dev/pkg/logging" + pkgreconciler "knative.dev/pkg/reconciler" +) + +const ( + nilPubsubableReason = "NilPubsubable" + pullSubscriptionGetFailedReason = "PullSubscriptionGetFailed" + pullSubscriptionCreateFailedReason = "PullSubscriptionCreateFailed" + PullSubscriptionStatusPropagateFailedReason = "PullSubscriptionStatusPropagateFailed" +) + +type PubSubBase struct { + *reconciler.Base + + // For dealing with Topics and Pullsubscriptions + pubsubClient clientset.Interface + + // What do we tag receive adapter as. + receiveAdapterName string + + // What type of receive adapter to use. + adapterType string +} + +// ReconcilePubSub reconciles Topic / PullSubscription given a PubSubSpec. +// Sets the following Conditions in the Status field appropriately: +// "TopicReady", and "PullSubscriptionReady" +// Also sets the following fields in the pubsubable.Status upon success +// TopicID, ProjectID, and SinkURI +func (psb *PubSubBase) ReconcilePubSub(ctx context.Context, pubsubable duck.PubSubable, topic, resourceGroup string) (*inteventsv1alpha1.Topic, *inteventsv1alpha1.PullSubscription, error) { + if pubsubable == nil { + return nil, nil, fmt.Errorf("nil pubsubable passed in") + } + namespace := pubsubable.GetObjectMeta().GetNamespace() + name := pubsubable.GetObjectMeta().GetName() + spec := pubsubable.PubSubSpec() + status := pubsubable.PubSubStatus() + + topics := psb.pubsubClient.InternalV1alpha1().Topics(namespace) + t, err := topics.Get(name, v1.GetOptions{}) + + if err != nil { + if !apierrs.IsNotFound(err) { + logging.FromContext(ctx).Desugar().Error("Failed to get Topics", zap.Error(err)) + return nil, nil, fmt.Errorf("failed to get Topics: %w", err) + } + args := &resources.TopicArgs{ + Namespace: namespace, + Name: name, + Spec: spec, + Owner: pubsubable, + Topic: topic, + Labels: resources.GetLabels(psb.receiveAdapterName, name), + } + newTopic := resources.MakeTopic(args) + t, err = topics.Create(newTopic) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to create Topic", zap.Any("topic", newTopic), zap.Error(err)) + return nil, nil, fmt.Errorf("failed to create Topic: %w", err) + } + } + + cs := pubsubable.ConditionSet() + + if err := propagateTopicStatus(t, status, cs, topic); err != nil { + return t, nil, err + } + + ps, err := psb.ReconcilePullSubscription(ctx, pubsubable, topic, resourceGroup, false) + if err != nil { + return t, ps, err + } + return t, ps, nil +} + +func (psb *PubSubBase) ReconcilePullSubscription(ctx context.Context, pubsubable duck.PubSubable, topic, resourceGroup string, isPushCompatible bool) (*inteventsv1alpha1.PullSubscription, pkgreconciler.Event) { + if pubsubable == nil { + logging.FromContext(ctx).Desugar().Error("Nil pubsubable passed in") + return nil, pkgreconciler.NewEvent(corev1.EventTypeWarning, nilPubsubableReason, "nil pubsubable passed in") + } + namespace := pubsubable.GetObjectMeta().GetNamespace() + name := pubsubable.GetObjectMeta().GetName() + annotations := pubsubable.GetObjectMeta().GetAnnotations() + spec := pubsubable.PubSubSpec() + status := pubsubable.PubSubStatus() + + cs := pubsubable.ConditionSet() + + pullSubscriptions := psb.pubsubClient.InternalV1alpha1().PullSubscriptions(namespace) + ps, err := pullSubscriptions.Get(name, v1.GetOptions{}) + if err != nil { + if !apierrs.IsNotFound(err) { + logging.FromContext(ctx).Desugar().Error("Failed to get PullSubscription", zap.Error(err)) + return nil, pkgreconciler.NewEvent(corev1.EventTypeWarning, pullSubscriptionGetFailedReason, "Getting PullSubscription failed with: %s", err.Error()) + } + args := &resources.PullSubscriptionArgs{ + Namespace: namespace, + Name: name, + Spec: spec, + Owner: pubsubable, + Topic: topic, + AdapterType: psb.adapterType, + Labels: resources.GetLabels(psb.receiveAdapterName, name), + Annotations: resources.GetAnnotations(annotations, resourceGroup), + } + if isPushCompatible { + args.Mode = inteventsv1alpha1.ModePushCompatible + } + + newPS := resources.MakePullSubscription(args) + logging.FromContext(ctx).Desugar().Debug("Creating PullSubscription", zap.Any("ps", newPS)) + ps, err = pullSubscriptions.Create(newPS) + if err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to create PullSubscription", zap.Any("ps", newPS), zap.Error(err)) + return nil, pkgreconciler.NewEvent(corev1.EventTypeWarning, pullSubscriptionCreateFailedReason, "Creating PullSubscription failed with: %s", err.Error()) + } + } + + if err := propagatePullSubscriptionStatus(ps, status, cs); err != nil { + logging.FromContext(ctx).Desugar().Error("Failed to propagate PullSubscription status: %s", zap.Error(err)) + return ps, pkgreconciler.NewEvent(corev1.EventTypeWarning, PullSubscriptionStatusPropagateFailedReason, "Failed to propagate PullSubscription status: %s", err.Error()) + } + + status.SinkURI = ps.Status.SinkURI + return ps, nil +} + +func propagatePullSubscriptionStatus(ps *inteventsv1alpha1.PullSubscription, status *duckv1alpha1.PubSubStatus, cs *apis.ConditionSet) error { + pc := ps.Status.GetTopLevelCondition() + if pc == nil { + status.MarkPullSubscriptionNotConfigured(cs) + return fmt.Errorf("PullSubscription %q has not yet been reconciled", ps.Name) + } + switch { + case pc.Status == corev1.ConditionUnknown: + status.MarkPullSubscriptionUnknown(cs, pc.Reason, pc.Message) + return fmt.Errorf("the status of PullSubscription %q is Unknown", ps.Name) + case pc.Status == corev1.ConditionTrue: + status.MarkPullSubscriptionReady(cs) + case pc.Status == corev1.ConditionFalse: + status.MarkPullSubscriptionFailed(cs, pc.Reason, pc.Message) + return fmt.Errorf("the status of PullSubscription %q is False", ps.Name) + default: + status.MarkPullSubscriptionUnknown(cs, "PullSubscriptionUnknown", "The status of PullSubscription is invalid: %v", pc.Status) + return fmt.Errorf("the status of PullSubscription %q is invalid: %v", ps.Name, pc.Status) + } + return nil +} + +func propagateTopicStatus(t *inteventsv1alpha1.Topic, status *duckv1alpha1.PubSubStatus, cs *apis.ConditionSet, topic string) error { + tc := t.Status.GetTopLevelCondition() + if tc == nil { + status.MarkTopicNotConfigured(cs) + return fmt.Errorf("Topic %q has not yet been reconciled", t.Name) + } + + switch { + case tc.Status == corev1.ConditionUnknown: + status.MarkTopicUnknown(cs, tc.Reason, tc.Message) + return fmt.Errorf("the status of Topic %q is Unknown", t.Name) + case tc.Status == corev1.ConditionTrue: + // When the status of Topic is ConditionTrue, break here since we also need to check the ProjectID and TopicID before we make the Topic to be Ready. + break + case tc.Status == corev1.ConditionFalse: + status.MarkTopicFailed(cs, tc.Reason, tc.Message) + return fmt.Errorf("the status of Topic %q is False", t.Name) + default: + status.MarkTopicUnknown(cs, "TopicUnknown", "The status of Topic is invalid: %v", tc.Status) + return fmt.Errorf("the status of Topic %q is invalid: %v", t.Name, tc.Status) + } + if t.Status.ProjectID == "" { + status.MarkTopicFailed(cs, "TopicNotReady", "Topic %q did not expose projectid", t.Name) + return fmt.Errorf("Topic %q did not expose projectid", t.Name) + } + if t.Status.TopicID == "" { + status.MarkTopicFailed(cs, "TopicNotReady", "Topic %q did not expose topicid", t.Name) + return fmt.Errorf("Topic %q did not expose topicid", t.Name) + } + if t.Status.TopicID != topic { + status.MarkTopicFailed(cs, "TopicNotReady", "Topic %q mismatch: expected %q got %q", t.Name, topic, t.Status.TopicID) + return fmt.Errorf("Topic %q mismatch: expected %q got %q", t.Name, topic, t.Status.TopicID) + } + status.TopicID = t.Status.TopicID + status.ProjectID = t.Status.ProjectID + status.MarkTopicReady(cs) + return nil +} + +func (psb *PubSubBase) DeletePubSub(ctx context.Context, pubsubable duck.PubSubable) error { + if pubsubable == nil { + return fmt.Errorf("nil pubsubable passed in") + } + namespace := pubsubable.GetObjectMeta().GetNamespace() + name := pubsubable.GetObjectMeta().GetName() + status := pubsubable.PubSubStatus() + cs := pubsubable.ConditionSet() + + // Delete the topic + err := psb.pubsubClient.InternalV1alpha1().Topics(namespace).Delete(name, nil) + if err != nil && !apierrs.IsNotFound(err) { + logging.FromContext(ctx).Desugar().Error("Failed to delete Topic", zap.String("name", name), zap.Error(err)) + status.MarkTopicFailed(cs, "TopicDeleteFailed", "Failed to delete Topic: %s", err.Error()) + return fmt.Errorf("failed to delete topic: %w", err) + } + status.MarkTopicFailed(cs, "TopicDeleted", "Successfully deleted Topic: %s", name) + status.TopicID = "" + status.ProjectID = "" + + // Delete the pullsubscription + err = psb.pubsubClient.InternalV1alpha1().PullSubscriptions(namespace).Delete(name, nil) + if err != nil && !apierrs.IsNotFound(err) { + logging.FromContext(ctx).Desugar().Error("Failed to delete PullSubscription", zap.String("name", name), zap.Error(err)) + status.MarkPullSubscriptionFailed(cs, "PullSubscriptionDeleteFailed", "Failed to delete PullSubscription: %s", err.Error()) + return fmt.Errorf("failed to delete PullSubscription: %w", err) + } + status.MarkPullSubscriptionFailed(cs, "PullSubscriptionDeleted", "Successfully deleted PullSubscription: %s", name) + status.SinkURI = nil + return nil +} diff --git a/pkg/reconciler/intevents/reconciler_test.go b/pkg/reconciler/intevents/reconciler_test.go new file mode 100644 index 0000000000..36c10ab25b --- /dev/null +++ b/pkg/reconciler/intevents/reconciler_test.go @@ -0,0 +1,686 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Veroute.on 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package intevents + +import ( + "context" + "fmt" + "strings" + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + clientgotesting "k8s.io/client-go/testing" + + logtesting "knative.dev/pkg/logging/testing" + pkgtesting "knative.dev/pkg/reconciler/testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/knative-gcp/pkg/apis/duck/v1alpha1" + inteventsv1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + fakePubsubClient "github.com/google/knative-gcp/pkg/client/clientset/versioned/fake" + "github.com/google/knative-gcp/pkg/reconciler" + rectesting "github.com/google/knative-gcp/pkg/reconciler/testing" +) + +const ( + testNS = "test-namespace" + name = "obj-name" + testTopicID = "topic" + testProjectID = "project" + receiveAdapterName = "test-receive-adapter" + resourceGroup = "test-resource-group" + sinkName = "sink" + failedToPropagatePullSubscriptionStatusMsg = `Failed to propagate PullSubscription status` +) + +var ( + trueVal = true + + testTopicURI = "http://" + name + "-topic." + testNS + ".svc.cluster.local" + + secret = corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "google-cloud-key", + }, + Key: "key.json", + } + pubsubable = rectesting.NewCloudStorageSource(name, testNS) + + ignoreLastTransitionTime = cmp.FilterPath(func(p cmp.Path) bool { + return strings.HasSuffix(p.String(), "LastTransitionTime.Inner.Time") + }, cmp.Ignore()) +) + +// Returns an ownerref for the test object +func ownerRef() metav1.OwnerReference { + return metav1.OwnerReference{ + APIVersion: "events.cloud.google.com/v1alpha1", + Kind: "CloudStorageSource", + Name: name, + UID: "test-storage-uid", + Controller: &trueVal, + BlockOwnerDeletion: &trueVal, + } +} + +func TestCreates(t *testing.T) { + testCases := []struct { + name string + objects []runtime.Object + expectedTopic *inteventsv1alpha1.Topic + expectedPS *inteventsv1alpha1.PullSubscription + expectedErr string + wantCreates []runtime.Object + }{{ + name: "topic does not exist, created, not yet been reconciled", + expectedTopic: rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Secret: &secret, + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + expectedPS: nil, + expectedErr: fmt.Sprintf("Topic %q has not yet been reconciled", name), + wantCreates: []runtime.Object{ + rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + }, + }, { + name: "topic exists but is not yet been reconciled", + objects: []runtime.Object{ + rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + }, + expectedTopic: rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Secret: &secret, + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + expectedPS: nil, + expectedErr: fmt.Sprintf("Topic %q has not yet been reconciled", name), + }, { + name: "topic exists and is ready but no projectid", + objects: []runtime.Object{ + rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicReady(testTopicID), + rectesting.WithTopicAddress(testTopicURI), + ), + }, + expectedTopic: rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Secret: &secret, + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicReady(testTopicID), + rectesting.WithTopicAddress(testTopicURI), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + expectedPS: nil, + expectedErr: fmt.Sprintf("Topic %q did not expose projectid", name), + }, { + name: "topic exists and the status of topic is false", + objects: []runtime.Object{ + rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicProjectID(testProjectID), + rectesting.WithTopicFailed(), + ), + }, + expectedTopic: rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Secret: &secret, + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicFailed(), + rectesting.WithTopicProjectID(testProjectID), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + expectedPS: nil, + expectedErr: fmt.Sprintf("the status of Topic %q is False", name), + }, { + name: "topic exists and the status of topic is unknown", + objects: []runtime.Object{ + rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicProjectID(testProjectID), + rectesting.WithTopicUnknown(), + ), + }, + expectedTopic: rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Secret: &secret, + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicUnknown(), + rectesting.WithTopicProjectID(testProjectID), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + expectedPS: nil, + expectedErr: fmt.Sprintf("the status of Topic %q is Unknown", name), + }, { + name: "topic exists and is ready but no topicid", + objects: []runtime.Object{ + rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicProjectID(testProjectID), + rectesting.WithTopicReady(""), + rectesting.WithTopicAddress(testTopicURI), + ), + }, + expectedTopic: rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Secret: &secret, + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicReady(""), + rectesting.WithTopicProjectID(testProjectID), + rectesting.WithTopicAddress(testTopicURI), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + expectedPS: nil, + expectedErr: fmt.Sprintf("Topic %q did not expose topicid", name), + }, { + name: "topic exists and is ready, pullsubscription created, not yet been reconciled", + objects: []runtime.Object{ + rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicProjectID(testProjectID), + rectesting.WithTopicReady(testTopicID), + rectesting.WithTopicAddress(testTopicURI), + ), + }, + expectedTopic: rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Secret: &secret, + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicReady(testTopicID), + rectesting.WithTopicProjectID(testProjectID), + rectesting.WithTopicAddress(testTopicURI), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + expectedPS: rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPullSubscriptionSpecWithNoDefaults(inteventsv1alpha1.PullSubscriptionSpec{ + Topic: testTopicID, + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + }, + }), + rectesting.WithPullSubscriptionLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithPullSubscriptionAnnotations(map[string]string{ + "metrics-resource-group": resourceGroup, + }), + rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + expectedErr: fmt.Sprintf("%s: PullSubscription %q has not yet been reconciled", failedToPropagatePullSubscriptionStatusMsg, name), + wantCreates: []runtime.Object{ + rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPullSubscriptionSpecWithNoDefaults(inteventsv1alpha1.PullSubscriptionSpec{ + Topic: testTopicID, + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + }, + }), + rectesting.WithPullSubscriptionLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithPullSubscriptionAnnotations(map[string]string{ + "metrics-resource-group": resourceGroup, + }), + rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + }, + }, { + name: "topic exists and is ready, pullsubscription exists, not yet been reconciled", + objects: []runtime.Object{ + rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicProjectID(testProjectID), + rectesting.WithTopicReady(testTopicID), + rectesting.WithTopicAddress(testTopicURI), + ), + rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPullSubscriptionSpecWithNoDefaults(inteventsv1alpha1.PullSubscriptionSpec{ + Topic: testTopicID, + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + }, + }), + rectesting.WithPullSubscriptionLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithPullSubscriptionAnnotations(map[string]string{ + "metrics-resource-group": resourceGroup, + }), + rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + }, + expectedTopic: rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Secret: &secret, + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicReady(testTopicID), + rectesting.WithTopicProjectID(testProjectID), + rectesting.WithTopicAddress(testTopicURI), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + expectedPS: rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPullSubscriptionSpecWithNoDefaults(inteventsv1alpha1.PullSubscriptionSpec{ + Topic: testTopicID, + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + }, + }), + rectesting.WithPullSubscriptionLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithPullSubscriptionAnnotations(map[string]string{ + "metrics-resource-group": resourceGroup, + }), + rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + expectedErr: fmt.Sprintf("%s: PullSubscription %q has not yet been reconciled", failedToPropagatePullSubscriptionStatusMsg, name), + }, { + name: "topic exists and is ready, pullsubscription exists and the status is false", + objects: []runtime.Object{ + rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicProjectID(testProjectID), + rectesting.WithTopicReady(testTopicID), + rectesting.WithTopicAddress(testTopicURI), + ), + rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPullSubscriptionSpecWithNoDefaults(inteventsv1alpha1.PullSubscriptionSpec{ + Topic: testTopicID, + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + }, + }), + rectesting.WithPullSubscriptionLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithPullSubscriptionAnnotations(map[string]string{ + "metrics-resource-group": resourceGroup, + }), + rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPullSubscriptionFailed(), + ), + }, + expectedTopic: rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Secret: &secret, + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicReady(testTopicID), + rectesting.WithTopicProjectID(testProjectID), + rectesting.WithTopicAddress(testTopicURI), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + expectedPS: rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPullSubscriptionSpecWithNoDefaults(inteventsv1alpha1.PullSubscriptionSpec{ + Topic: testTopicID, + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + }, + }), + rectesting.WithPullSubscriptionLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithPullSubscriptionAnnotations(map[string]string{ + "metrics-resource-group": resourceGroup, + }), + rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPullSubscriptionFailed(), + ), + expectedErr: fmt.Sprintf("%s: the status of PullSubscription %q is False", failedToPropagatePullSubscriptionStatusMsg, name), + }, { + name: "topic exists and is ready, pullsubscription exists and the status is unknown", + objects: []runtime.Object{ + rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicProjectID(testProjectID), + rectesting.WithTopicReady(testTopicID), + rectesting.WithTopicAddress(testTopicURI), + ), + rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPullSubscriptionSpecWithNoDefaults(inteventsv1alpha1.PullSubscriptionSpec{ + Topic: testTopicID, + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + }, + }), + rectesting.WithPullSubscriptionLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithPullSubscriptionAnnotations(map[string]string{ + "metrics-resource-group": resourceGroup, + }), + rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPullSubscriptionUnknown(), + ), + }, + expectedTopic: rectesting.NewTopic(name, testNS, + rectesting.WithTopicSpec(inteventsv1alpha1.TopicSpec{ + Secret: &secret, + Topic: testTopicID, + PropagationPolicy: "CreateDelete", + }), + rectesting.WithTopicLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithTopicReady(testTopicID), + rectesting.WithTopicProjectID(testProjectID), + rectesting.WithTopicAddress(testTopicURI), + rectesting.WithTopicOwnerReferences([]metav1.OwnerReference{ownerRef()}), + ), + expectedPS: rectesting.NewPullSubscriptionWithNoDefaults(name, testNS, + rectesting.WithPullSubscriptionSpecWithNoDefaults(inteventsv1alpha1.PullSubscriptionSpec{ + Topic: testTopicID, + PubSubSpec: v1alpha1.PubSubSpec{ + Secret: &secret, + }, + }), + rectesting.WithPullSubscriptionLabels(map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": name, + }), + rectesting.WithPullSubscriptionAnnotations(map[string]string{ + "metrics-resource-group": resourceGroup, + }), + rectesting.WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), + rectesting.WithPullSubscriptionUnknown(), + ), + expectedErr: fmt.Sprintf("%s: the status of PullSubscription %q is Unknown", failedToPropagatePullSubscriptionStatusMsg, name), + }} + + defer logtesting.ClearAll() + + for _, tc := range testCases { + cs := fakePubsubClient.NewSimpleClientset(tc.objects...) + + psBase := &PubSubBase{ + Base: &reconciler.Base{}, + pubsubClient: cs, + receiveAdapterName: receiveAdapterName, + } + psBase.Logger = logtesting.TestLogger(t) + + arl := pkgtesting.ActionRecorderList{cs} + topic, ps, err := psBase.ReconcilePubSub(context.Background(), pubsubable, testTopicID, resourceGroup) + + if (tc.expectedErr != "" && err == nil) || + (tc.expectedErr == "" && err != nil) || + (tc.expectedErr != "" && err != nil && tc.expectedErr != err.Error()) { + t.Errorf("Test case %q, Error mismatch, want: %q got: %q", tc.name, tc.expectedErr, err) + } + if diff := cmp.Diff(tc.expectedTopic, topic, ignoreLastTransitionTime); diff != "" { + t.Errorf("Test case %q, unexpected topic (-want, +got) = %v", tc.name, diff) + } + if diff := cmp.Diff(tc.expectedPS, ps, ignoreLastTransitionTime); diff != "" { + t.Errorf("Test case %q, unexpected pullsubscription (-want, +got) = %v", tc.name, diff) + } + + // Validate creates. + actions, err := arl.ActionsByVerb() + if err != nil { + t.Errorf("Error capturing actions by verb: %q", err) + } + for i, want := range tc.wantCreates { + if i >= len(actions.Creates) { + t.Errorf("Missing create: %#v", want) + continue + } + got := actions.Creates[i] + obj := got.GetObject() + if diff := cmp.Diff(want, obj); diff != "" { + t.Errorf("Unexpected create (-want, +got): %s", diff) + } + } + if got, want := len(actions.Creates), len(tc.wantCreates); got > want { + for _, extra := range actions.Creates[want:] { + t.Errorf("Extra create: %#v", extra.GetObject()) + } + } + } +} + +func TestDeletes(t *testing.T) { + testCases := []struct { + name string + wantDeletes []clientgotesting.DeleteActionImpl + expectedErr string + }{{ + name: "topic and pullsubscription deleeted", + expectedErr: "", + wantDeletes: []clientgotesting.DeleteActionImpl{ + { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Verb: "delete", + Resource: schema.GroupVersionResource{Group: "internal.events.cloud.google.com", Version: "v1alpha1", Resource: "topics"}, + }, + Name: name, + }, { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Verb: "delete", + Resource: schema.GroupVersionResource{Group: "internal.events.cloud.google.com", Version: "v1alpha1", Resource: "pullsubscriptions"}, + }, + Name: name, + }, + }, + }} + + defer logtesting.ClearAll() + + for _, tc := range testCases { + cs := fakePubsubClient.NewSimpleClientset() + + psBase := &PubSubBase{ + Base: &reconciler.Base{}, + pubsubClient: cs, + receiveAdapterName: receiveAdapterName, + } + psBase.Logger = logtesting.TestLogger(t) + + arl := pkgtesting.ActionRecorderList{cs} + err := psBase.DeletePubSub(context.Background(), pubsubable) + + if (tc.expectedErr != "" && err == nil) || + (tc.expectedErr == "" && err != nil) || + (tc.expectedErr != "" && err != nil && tc.expectedErr != err.Error()) { + t.Errorf("Error mismatch, want: %q got: %q", tc.expectedErr, err) + } + + // validate deletes + actions, err := arl.ActionsByVerb() + if err != nil { + t.Errorf("Error capturing actions by verb: %q", err) + } + for i, want := range tc.wantDeletes { + if i >= len(actions.Deletes) { + t.Errorf("Missing delete: %#v", want) + continue + } + got := actions.Deletes[i] + if got.GetName() != want.GetName() { + t.Errorf("Unexpected delete[%d]: %#v", i, got) + } + if got.GetResource() != want.GetResource() { + t.Errorf("Unexpected delete[%d]: %#v wanted: %#v", i, got, want) + } + } + if got, want := len(actions.Deletes), len(tc.wantDeletes); got > want { + for _, extra := range actions.Deletes[want:] { + t.Errorf("Extra delete: %s/%s", extra.GetNamespace(), extra.GetName()) + } + } + } +} diff --git a/pkg/reconciler/intevents/resources/annotations.go b/pkg/reconciler/intevents/resources/annotations.go new file mode 100644 index 0000000000..23d97bf2e1 --- /dev/null +++ b/pkg/reconciler/intevents/resources/annotations.go @@ -0,0 +1,26 @@ +/* +Copyright 2020 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +func GetAnnotations(original map[string]string, resourceGroup string) map[string]string { + annotations := original + if annotations == nil { + annotations = make(map[string]string) + } + annotations["metrics-resource-group"] = resourceGroup + return annotations +} diff --git a/pkg/reconciler/intevents/resources/labels.go b/pkg/reconciler/intevents/resources/labels.go new file mode 100644 index 0000000000..03a9c30f25 --- /dev/null +++ b/pkg/reconciler/intevents/resources/labels.go @@ -0,0 +1,24 @@ +/* +Copyright 2020 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +func GetLabels(receiveAdapterName, source string) map[string]string { + return map[string]string{ + "receive-adapter": receiveAdapterName, + "events.cloud.google.com/source-name": source, + } +} diff --git a/pkg/reconciler/intevents/resources/labels_test.go b/pkg/reconciler/intevents/resources/labels_test.go new file mode 100644 index 0000000000..e930aebac0 --- /dev/null +++ b/pkg/reconciler/intevents/resources/labels_test.go @@ -0,0 +1,35 @@ +/* +Copyright 2020 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + "testing" + + "github.com/google/go-cmp/cmp" +) + +func TestGetLabels(t *testing.T) { + want := map[string]string{ + "receive-adapter": "receive-adapter-name", + "events.cloud.google.com/source-name": "source", + } + got := GetLabels("receive-adapter-name", "source") + + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("unexpected (-want, +got) = %v", diff) + } +} diff --git a/pkg/reconciler/intevents/resources/pullsubscription.go b/pkg/reconciler/intevents/resources/pullsubscription.go new file mode 100644 index 0000000000..0ea5a6bd0a --- /dev/null +++ b/pkg/reconciler/intevents/resources/pullsubscription.go @@ -0,0 +1,73 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + duckv1 "knative.dev/pkg/apis/duck/v1" + "knative.dev/pkg/kmeta" + + duckv1alpha1 "github.com/google/knative-gcp/pkg/apis/duck/v1alpha1" + inteventsv1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" +) + +type PullSubscriptionArgs struct { + Namespace string + Name string + Spec *duckv1alpha1.PubSubSpec + Owner kmeta.OwnerRefable + Topic string + AdapterType string + Mode inteventsv1alpha1.ModeType + Labels map[string]string + Annotations map[string]string +} + +// MakePullSubscription creates the spec for, but does not create, a GCP PullSubscription +// for a given GCS. +func MakePullSubscription(args *PullSubscriptionArgs) *inteventsv1alpha1.PullSubscription { + ps := &inteventsv1alpha1.PullSubscription{ + ObjectMeta: metav1.ObjectMeta{ + Name: args.Name, + Namespace: args.Namespace, + Labels: args.Labels, + Annotations: args.Annotations, + OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(args.Owner)}, + }, + Spec: inteventsv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + IdentitySpec: duckv1alpha1.IdentitySpec{ + GoogleServiceAccount: args.Spec.IdentitySpec.GoogleServiceAccount, + }, + Secret: args.Spec.Secret, + Project: args.Spec.Project, + SourceSpec: duckv1.SourceSpec{ + Sink: args.Spec.SourceSpec.Sink, + }, + }, + Topic: args.Topic, + AdapterType: args.AdapterType, + Mode: args.Mode, + }, + } + if args.Spec.CloudEventOverrides != nil && args.Spec.CloudEventOverrides.Extensions != nil { + ps.Spec.SourceSpec.CloudEventOverrides = &duckv1.CloudEventOverrides{ + Extensions: args.Spec.CloudEventOverrides.Extensions, + } + } + return ps +} diff --git a/pkg/reconciler/intevents/resources/pullsubscription_test.go b/pkg/reconciler/intevents/resources/pullsubscription_test.go new file mode 100644 index 0000000000..3eeab796df --- /dev/null +++ b/pkg/reconciler/intevents/resources/pullsubscription_test.go @@ -0,0 +1,133 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + duckv1alpha1 "github.com/google/knative-gcp/pkg/apis/duck/v1alpha1" + "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" + inteventsv1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +func TestMakePullSubscription(t *testing.T) { + source := &v1alpha1.CloudStorageSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bucket-name", + Namespace: "bucket-namespace", + UID: "bucket-uid", + }, + Spec: v1alpha1.CloudStorageSourceSpec{ + Bucket: "this-bucket", + PubSubSpec: duckv1alpha1.PubSubSpec{ + Project: "project-123", + Secret: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "eventing-secret-name", + }, + Key: "eventing-secret-key", + }, + SourceSpec: duckv1.SourceSpec{ + Sink: duckv1.Destination{ + Ref: &duckv1.KReference{ + APIVersion: "v1", + Kind: "Kitchen", + Name: "sink", + }, + }, + CloudEventOverrides: &duckv1.CloudEventOverrides{ + Extensions: map[string]string{ + "foo": "bar", + }, + }, + }, + }, + }, + } + args := &PullSubscriptionArgs{ + Namespace: source.Namespace, + Name: source.Name, + Spec: &source.Spec.PubSubSpec, + Owner: source, + Topic: "topic-abc", + AdapterType: "google.storage", + Annotations: GetAnnotations(nil, "storages.events.cloud.google.com"), + Labels: map[string]string{ + "receive-adapter": "storage.events.cloud.google.com", + "events.cloud.google.com/source-name": source.Name, + }, + } + got := MakePullSubscription(args) + + yes := true + want := &inteventsv1alpha1.PullSubscription{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "bucket-namespace", + Name: "bucket-name", + Labels: map[string]string{ + "receive-adapter": "storage.events.cloud.google.com", + "events.cloud.google.com/source-name": "bucket-name", + }, + Annotations: map[string]string{ + "metrics-resource-group": "storages.events.cloud.google.com", + }, + OwnerReferences: []metav1.OwnerReference{{ + APIVersion: "events.cloud.google.com/v1alpha1", + Kind: "CloudStorageSource", + Name: "bucket-name", + UID: "bucket-uid", + Controller: &yes, + BlockOwnerDeletion: &yes, + }}, + }, + Spec: inteventsv1alpha1.PullSubscriptionSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Secret: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "eventing-secret-name", + }, + Key: "eventing-secret-key", + }, + Project: "project-123", + SourceSpec: duckv1.SourceSpec{ + Sink: duckv1.Destination{ + Ref: &duckv1.KReference{ + APIVersion: "v1", + Kind: "Kitchen", + Name: "sink", + }, + }, + CloudEventOverrides: &duckv1.CloudEventOverrides{ + Extensions: map[string]string{ + "foo": "bar", + }, + }, + }, + }, + Topic: "topic-abc", + AdapterType: "google.storage", + }, + } + + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("unexpected (-want, +got) = %v", diff) + } +} diff --git a/pkg/reconciler/intevents/resources/topic.go b/pkg/reconciler/intevents/resources/topic.go new file mode 100644 index 0000000000..964eb4ac33 --- /dev/null +++ b/pkg/reconciler/intevents/resources/topic.go @@ -0,0 +1,56 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/kmeta" + + duckv1alpha1 "github.com/google/knative-gcp/pkg/apis/duck/v1alpha1" + inteventsv1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" +) + +type TopicArgs struct { + Namespace string + Name string + Spec *duckv1alpha1.PubSubSpec + Owner kmeta.OwnerRefable + Topic string + Labels map[string]string +} + +// MakeTopic creates the spec for, but does not create, a GCP Topic +// for a given GCS. +func MakeTopic(args *TopicArgs) *inteventsv1alpha1.Topic { + return &inteventsv1alpha1.Topic{ + ObjectMeta: metav1.ObjectMeta{ + Name: args.Name, + Namespace: args.Namespace, + Labels: args.Labels, + OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(args.Owner)}, + }, + Spec: inteventsv1alpha1.TopicSpec{ + IdentitySpec: duckv1alpha1.IdentitySpec{ + GoogleServiceAccount: args.Spec.IdentitySpec.GoogleServiceAccount, + }, + Secret: args.Spec.Secret, + Project: args.Spec.Project, + Topic: args.Topic, + PropagationPolicy: inteventsv1alpha1.TopicPolicyCreateDelete, + }, + } +} diff --git a/pkg/reconciler/intevents/resources/topic_test.go b/pkg/reconciler/intevents/resources/topic_test.go new file mode 100644 index 0000000000..83cbe31cd0 --- /dev/null +++ b/pkg/reconciler/intevents/resources/topic_test.go @@ -0,0 +1,185 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + duckv1alpha1 "github.com/google/knative-gcp/pkg/apis/duck/v1alpha1" + "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" + inteventsv1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +func TestMakeTopicWithCloudStorageSource(t *testing.T) { + source := &v1alpha1.CloudStorageSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: "storage-name", + Namespace: "storage-namespace", + UID: "storage-uid", + }, + Spec: v1alpha1.CloudStorageSourceSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Project: "project-123", + Secret: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "eventing-secret-name", + }, + Key: "eventing-secret-key", + }, + SourceSpec: duckv1.SourceSpec{ + Sink: duckv1.Destination{ + Ref: &duckv1.KReference{ + APIVersion: "v1", + Kind: "Kitchen", + Name: "sink", + }, + }, + }, + }, + Bucket: "this-bucket", + }, + } + args := &TopicArgs{ + Namespace: source.Namespace, + Name: source.Name, + Spec: &source.Spec.PubSubSpec, + Owner: source, + Topic: "topic-abc", + Labels: map[string]string{ + "receive-adapter": "storage.events.cloud.google.com", + "source": source.Name, + }, + } + got := MakeTopic(args) + + yes := true + want := &inteventsv1alpha1.Topic{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "storage-namespace", + Name: "storage-name", + Labels: map[string]string{ + "receive-adapter": "storage.events.cloud.google.com", + "source": "storage-name", + }, + OwnerReferences: []metav1.OwnerReference{{ + APIVersion: "events.cloud.google.com/v1alpha1", + Kind: "CloudStorageSource", + Name: "storage-name", + UID: "storage-uid", + Controller: &yes, + BlockOwnerDeletion: &yes, + }}, + }, + Spec: inteventsv1alpha1.TopicSpec{ + Secret: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "eventing-secret-name", + }, + Key: "eventing-secret-key", + }, + Project: "project-123", + Topic: "topic-abc", + PropagationPolicy: inteventsv1alpha1.TopicPolicyCreateDelete, + }, + } + + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("unexpected (-want, +got) = %v", diff) + } +} + +func TestMakeTopicWithCloudSchedulerSource(t *testing.T) { + source := &v1alpha1.CloudSchedulerSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: "scheduler-name", + Namespace: "scheduler-namespace", + UID: "scheduler-uid", + }, + Spec: v1alpha1.CloudSchedulerSourceSpec{ + PubSubSpec: duckv1alpha1.PubSubSpec{ + Project: "project-123", + Secret: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "eventing-secret-name", + }, + Key: "eventing-secret-key", + }, + SourceSpec: duckv1.SourceSpec{ + Sink: duckv1.Destination{ + Ref: &duckv1.KReference{ + APIVersion: "v1", + Kind: "Kitchen", + Name: "sink", + }, + }, + }, + }, + }, + } + args := &TopicArgs{ + Namespace: source.Namespace, + Name: source.Name, + Spec: &source.Spec.PubSubSpec, + Owner: source, + Topic: "topic-abc", + Labels: map[string]string{ + "receive-adapter": "scheduler.events.cloud.google.com", + "source": source.Name, + }, + } + got := MakeTopic(args) + + yes := true + want := &inteventsv1alpha1.Topic{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "scheduler-namespace", + Name: "scheduler-name", + Labels: map[string]string{ + "receive-adapter": "scheduler.events.cloud.google.com", + "source": "scheduler-name", + }, + OwnerReferences: []metav1.OwnerReference{{ + APIVersion: "events.cloud.google.com/v1alpha1", + Kind: "CloudSchedulerSource", + Name: "scheduler-name", + UID: "scheduler-uid", + Controller: &yes, + BlockOwnerDeletion: &yes, + }}, + }, + Spec: inteventsv1alpha1.TopicSpec{ + Secret: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "eventing-secret-name", + }, + Key: "eventing-secret-key", + }, + Project: "project-123", + Topic: "topic-abc", + PropagationPolicy: inteventsv1alpha1.TopicPolicyCreateDelete, + }, + } + + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("unexpected (-want, +got) = %v", diff) + } +} diff --git a/pkg/reconciler/intevents/topic/controller.go b/pkg/reconciler/intevents/topic/controller.go index 8a2dc5f2e5..fcbfee6858 100644 --- a/pkg/reconciler/intevents/topic/controller.go +++ b/pkg/reconciler/intevents/topic/controller.go @@ -32,7 +32,7 @@ import ( "github.com/google/knative-gcp/pkg/reconciler" "github.com/google/knative-gcp/pkg/reconciler/identity" "github.com/google/knative-gcp/pkg/reconciler/identity/iam" - "github.com/google/knative-gcp/pkg/reconciler/pubsub" + "github.com/google/knative-gcp/pkg/reconciler/intevents" topicinformer "github.com/google/knative-gcp/pkg/client/injection/informers/intevents/v1alpha1/topic" topicreconciler "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/topic" @@ -82,7 +82,7 @@ func newControllerWithIAMPolicyManager( logger.Fatal("Failed to process env var", zap.Error(err)) } - pubsubBase := &pubsub.PubSubBase{ + pubsubBase := &intevents.PubSubBase{ Base: reconciler.NewBase(ctx, controllerAgentName, cmw), } diff --git a/pkg/reconciler/intevents/topic/topic.go b/pkg/reconciler/intevents/topic/topic.go index 757a7b36f5..4ea466c85f 100644 --- a/pkg/reconciler/intevents/topic/topic.go +++ b/pkg/reconciler/intevents/topic/topic.go @@ -43,8 +43,8 @@ import ( listers "github.com/google/knative-gcp/pkg/client/listers/intevents/v1alpha1" gpubsub "github.com/google/knative-gcp/pkg/gclient/pubsub" "github.com/google/knative-gcp/pkg/reconciler/identity" + "github.com/google/knative-gcp/pkg/reconciler/intevents" "github.com/google/knative-gcp/pkg/reconciler/intevents/topic/resources" - "github.com/google/knative-gcp/pkg/reconciler/pubsub" gstatus "google.golang.org/grpc/status" ) @@ -61,7 +61,7 @@ const ( // Reconciler implements controller.Reconciler for Topic resources. type Reconciler struct { - *pubsub.PubSubBase + *intevents.PubSubBase // identity reconciler for reconciling workload identity. *identity.Identity // topicLister index properties about topics. diff --git a/pkg/reconciler/intevents/topic/topic_test.go b/pkg/reconciler/intevents/topic/topic_test.go index bdc62376e5..df174e142c 100644 --- a/pkg/reconciler/intevents/topic/topic_test.go +++ b/pkg/reconciler/intevents/topic/topic_test.go @@ -43,8 +43,8 @@ import ( "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/topic" gpubsub "github.com/google/knative-gcp/pkg/gclient/pubsub/testing" "github.com/google/knative-gcp/pkg/reconciler" + "github.com/google/knative-gcp/pkg/reconciler/intevents" "github.com/google/knative-gcp/pkg/reconciler/intevents/topic/resources" - "github.com/google/knative-gcp/pkg/reconciler/pubsub" . "github.com/google/knative-gcp/pkg/reconciler/testing" ) @@ -587,7 +587,7 @@ func TestAllCases(t *testing.T) { defer logtesting.ClearAll() table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher, testData map[string]interface{}) controller.Reconciler { - pubsubBase := &pubsub.PubSubBase{ + pubsubBase := &intevents.PubSubBase{ Base: reconciler.NewBase(ctx, controllerAgentName, cmw), } r := &Reconciler{ @@ -689,7 +689,7 @@ func makeFalseStatusPublisher(reason, message string) *servingv1.Service { } func newPublisher() *servingv1.Service { - topic := NewTopic(topicName, testNS, + t := NewTopic(topicName, testNS, WithTopicUID(topicUID), WithTopicSpec(pubsubv1alpha1.TopicSpec{ Project: testProject, @@ -698,7 +698,7 @@ func newPublisher() *servingv1.Service { })) args := &resources.PublisherArgs{ Image: testImage, - Topic: topic, + Topic: t, Labels: resources.GetLabels(controllerAgentName, topicName), } return resources.MakePublisher(args)