From 7b4cbcfe97a84bec227e0fc9ce14690c84393702 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Wed, 17 Jun 2020 08:30:54 -0700 Subject: [PATCH 01/28] moving to cev2 publisher and receive adapter updating converters --- cmd/broker/ingress/main.go | 6 +- cmd/broker/ingress/wire.go | 5 +- cmd/broker/ingress/wire_gen.go | 7 +- cmd/pubsub/publisher/main.go | 49 +- cmd/pubsub/publisher/wire.go | 39 + cmd/pubsub/publisher/wire_gen.go | 25 + cmd/pubsub/receive_adapter/main.go | 136 ++- cmd/pubsub/receive_adapter/wire.go | 46 + cmd/pubsub/receive_adapter/wire_gen.go | 29 + pkg/broker/handler/fanout.go | 1 - pkg/broker/ingress/handler.go | 5 +- pkg/pubsub/adapter/adapter.go | 327 +++---- pkg/pubsub/adapter/adapter_test.go | 798 +++++++++--------- pkg/pubsub/adapter/context/errs.go | 25 + pkg/pubsub/adapter/context/project.go | 38 + pkg/pubsub/adapter/context/project_test.go | 39 + pkg/pubsub/adapter/context/subscription.go | 38 + .../adapter/context/subscription_test.go | 39 + pkg/pubsub/adapter/context/topic.go | 38 + pkg/pubsub/adapter/context/topic_test.go | 39 + pkg/pubsub/adapter/converters/auditlogs.go | 22 +- .../adapter/converters/auditlogs_test.go | 33 +- pkg/pubsub/adapter/converters/build.go | 53 +- pkg/pubsub/adapter/converters/build_test.go | 102 ++- pkg/pubsub/adapter/converters/converters.go | 14 +- pkg/pubsub/adapter/converters/pubsub.go | 122 +-- pkg/pubsub/adapter/converters/pubsub_test.go | 142 +--- pkg/pubsub/adapter/converters/push.go | 31 + pkg/pubsub/adapter/converters/scheduler.go | 60 +- .../adapter/converters/scheduler_test.go | 100 +-- pkg/pubsub/adapter/converters/storage.go | 65 +- pkg/pubsub/adapter/converters/storage_test.go | 166 ++-- pkg/pubsub/adapter/providers.go | 33 + pkg/pubsub/adapter/stats_reporter.go | 44 +- pkg/pubsub/adapter/stats_reporter_test.go | 21 +- pkg/pubsub/publisher/providers.go | 26 + pkg/pubsub/publisher/publisher.go | 152 ++-- .../args.go => utils/clients/factories.go} | 27 +- 38 files changed, 1615 insertions(+), 1327 deletions(-) create mode 100644 cmd/pubsub/publisher/wire.go create mode 100644 cmd/pubsub/publisher/wire_gen.go create mode 100644 cmd/pubsub/receive_adapter/wire.go create mode 100644 cmd/pubsub/receive_adapter/wire_gen.go create mode 100644 pkg/pubsub/adapter/context/errs.go create mode 100644 pkg/pubsub/adapter/context/project.go create mode 100644 pkg/pubsub/adapter/context/project_test.go create mode 100644 pkg/pubsub/adapter/context/subscription.go create mode 100644 pkg/pubsub/adapter/context/subscription_test.go create mode 100644 pkg/pubsub/adapter/context/topic.go create mode 100644 pkg/pubsub/adapter/context/topic_test.go create mode 100644 pkg/pubsub/adapter/converters/push.go create mode 100644 pkg/pubsub/adapter/providers.go create mode 100644 pkg/pubsub/publisher/providers.go rename pkg/{broker/ingress/args.go => utils/clients/factories.go} (67%) diff --git a/cmd/broker/ingress/main.go b/cmd/broker/ingress/main.go index 49a28baca5..5010140325 100644 --- a/cmd/broker/ingress/main.go +++ b/cmd/broker/ingress/main.go @@ -17,11 +17,11 @@ limitations under the License. package main import ( - "github.com/google/knative-gcp/pkg/broker/ingress" metadataClient "github.com/google/knative-gcp/pkg/gclient/metadata" "github.com/google/knative-gcp/pkg/metrics" "github.com/google/knative-gcp/pkg/utils" "github.com/google/knative-gcp/pkg/utils/appcredentials" + "github.com/google/knative-gcp/pkg/utils/clients" "github.com/google/knative-gcp/pkg/utils/mainhelper" "go.uber.org/zap" @@ -59,8 +59,8 @@ func main() { ingress, err := InitializeHandler( ctx, - ingress.Port(env.Port), - ingress.ProjectID(projectID), + clients.Port(env.Port), + clients.ProjectID(projectID), metrics.PodName(env.PodName), metrics.ContainerName(component), ) diff --git a/cmd/broker/ingress/wire.go b/cmd/broker/ingress/wire.go index fa8e4343ab..590cb991a8 100644 --- a/cmd/broker/ingress/wire.go +++ b/cmd/broker/ingress/wire.go @@ -24,13 +24,14 @@ import ( "github.com/google/knative-gcp/pkg/broker/config/volume" "github.com/google/knative-gcp/pkg/broker/ingress" "github.com/google/knative-gcp/pkg/metrics" + "github.com/google/knative-gcp/pkg/utils/clients" "github.com/google/wire" ) func InitializeHandler( ctx context.Context, - port ingress.Port, - projectID ingress.ProjectID, + port clients.Port, + projectID clients.ProjectID, podName metrics.PodName, containerName metrics.ContainerName, ) (*ingress.Handler, error) { diff --git a/cmd/broker/ingress/wire_gen.go b/cmd/broker/ingress/wire_gen.go index 7019e24743..f711fe6110 100644 --- a/cmd/broker/ingress/wire_gen.go +++ b/cmd/broker/ingress/wire_gen.go @@ -10,18 +10,19 @@ import ( "github.com/google/knative-gcp/pkg/broker/config/volume" "github.com/google/knative-gcp/pkg/broker/ingress" "github.com/google/knative-gcp/pkg/metrics" + "github.com/google/knative-gcp/pkg/utils/clients" ) // Injectors from wire.go: -func InitializeHandler(ctx context.Context, port ingress.Port, projectID ingress.ProjectID, podName metrics.PodName, containerName metrics.ContainerName) (*ingress.Handler, error) { - httpMessageReceiver := ingress.NewHTTPMessageReceiver(port) +func InitializeHandler(ctx context.Context, port clients.Port, projectID clients.ProjectID, podName metrics.PodName, containerName metrics.ContainerName) (*ingress.Handler, error) { + httpMessageReceiver := clients.NewHTTPMessageReceiver(port) v := _wireValue readonlyTargets, err := volume.NewTargetsFromFile(v...) if err != nil { return nil, err } - client, err := ingress.NewPubsubClient(ctx, projectID) + client, err := clients.NewPubsubClient(ctx, projectID) if err != nil { return nil, err } diff --git a/cmd/pubsub/publisher/main.go b/cmd/pubsub/publisher/main.go index 66e58c7e16..561c125b28 100644 --- a/cmd/pubsub/publisher/main.go +++ b/cmd/pubsub/publisher/main.go @@ -21,17 +21,22 @@ import ( "flag" "log" - "cloud.google.com/go/compute/metadata" + metadataClient "github.com/google/knative-gcp/pkg/gclient/metadata" + . "github.com/google/knative-gcp/pkg/pubsub/publisher" + tracingconfig "github.com/google/knative-gcp/pkg/tracing" + "github.com/google/knative-gcp/pkg/utils" + "github.com/google/knative-gcp/pkg/utils/appcredentials" + "github.com/google/knative-gcp/pkg/utils/clients" "github.com/kelseyhightower/envconfig" "go.uber.org/zap" "go.uber.org/zap/zapcore" "knative.dev/eventing/pkg/tracing" - - "github.com/google/knative-gcp/pkg/pubsub/publisher" - tracingconfig "github.com/google/knative-gcp/pkg/tracing" ) type envConfig struct { + // Environment variable containing the port for the publisher. + Port int `envconfig:"PORT" default:"8080"` + // Environment variable containing project id. Project string `envconfig:"PROJECT_ID"` @@ -47,6 +52,8 @@ type envConfig struct { } func main() { + appcredentials.MustExistOrUnsetEnv() + flag.Parse() ctx := context.Background() @@ -62,15 +69,15 @@ func main() { logger.Fatal("Failed to process env var", zap.Error(err)) } - if env.Project == "" { - project, err := metadata.ProjectID() - if err != nil { - logger.Fatal("failed to find project id. ", zap.Error(err)) - } - env.Project = project + projectID, err := utils.ProjectID(env.Project, metadataClient.NewDefaultMetadataClient()) + if err != nil { + logger.Fatal("Failed to retrieve project id", zap.Error(err)) } - logger.Info("Using project.", zap.String("project", env.Project)) + topicID := env.Topic + if topicID == "" { + logger.Fatal("Failed to retrieve topic id", zap.Error(err)) + } tracingConfig, err := tracingconfig.JSONToConfig(env.TracingConfigJson) if err != nil { @@ -80,13 +87,21 @@ func main() { logger.Error("Failed to setup tracing", zap.Error(err), zap.Any("tracingConfig", tracingConfig)) } - startable := &publisher.Publisher{ - ProjectID: env.Project, - TopicID: env.Topic, + logger.Info("Initializing publisher", zap.String("Project ID", projectID), zap.String("Topic ID", topicID)) + + publisher, err := InitializePublisher( + ctx, + clients.Port(env.Port), + clients.ProjectID(projectID), + TopicID(topicID), + ) + + if err != nil { + logger.Fatal("Unable to create publisher", zap.Error(err)) } - logger.Info("Starting Pub/Sub Publisher.", zap.Any("publisher", startable)) - if err := startable.Start(ctx); err != nil { - logger.Fatal("failed to start publisher: ", zap.Error(err)) + logger.Info("Starting publisher", zap.Any("publisher", publisher)) + if err := publisher.Start(ctx); err != nil { + logger.Fatal("Failed to start publisher", zap.Error(err)) } } diff --git a/cmd/pubsub/publisher/wire.go b/cmd/pubsub/publisher/wire.go new file mode 100644 index 0000000000..8c0e95f988 --- /dev/null +++ b/cmd/pubsub/publisher/wire.go @@ -0,0 +1,39 @@ +// +build wireinject + +/* +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 main + +import ( + "context" + + "github.com/google/knative-gcp/pkg/pubsub/publisher" + "github.com/google/knative-gcp/pkg/utils/clients" + + "github.com/google/wire" +) + +func InitializePublisher( + ctx context.Context, + port clients.Port, + projectID clients.ProjectID, + topicID publisher.TopicID, +) (*publisher.Publisher, error) { + panic(wire.Build( + publisher.PublisherSet, + )) +} diff --git a/cmd/pubsub/publisher/wire_gen.go b/cmd/pubsub/publisher/wire_gen.go new file mode 100644 index 0000000000..674f21ada8 --- /dev/null +++ b/cmd/pubsub/publisher/wire_gen.go @@ -0,0 +1,25 @@ +// Code generated by Wire. DO NOT EDIT. + +//go:generate wire +//+build !wireinject + +package main + +import ( + "context" + "github.com/google/knative-gcp/pkg/pubsub/publisher" + "github.com/google/knative-gcp/pkg/utils/clients" +) + +// Injectors from wire.go: + +func InitializePublisher(ctx context.Context, port clients.Port, projectID clients.ProjectID, topicID publisher.TopicID) (*publisher.Publisher, error) { + httpMessageReceiver := clients.NewHTTPMessageReceiver(port) + client, err := clients.NewPubsubClient(ctx, projectID) + if err != nil { + return nil, err + } + topic := publisher.NewPubSubTopic(ctx, client, topicID) + publisherPublisher := publisher.NewPublisher(ctx, httpMessageReceiver, client, topic) + return publisherPublisher, nil +} diff --git a/cmd/pubsub/receive_adapter/main.go b/cmd/pubsub/receive_adapter/main.go index 6d3da83358..f2d454b7ed 100644 --- a/cmd/pubsub/receive_adapter/main.go +++ b/cmd/pubsub/receive_adapter/main.go @@ -19,35 +19,98 @@ package main import ( "flag" "fmt" - - "knative.dev/eventing/pkg/tracing" - - "cloud.google.com/go/compute/metadata" - "github.com/google/knative-gcp/pkg/pubsub/adapter" - tracingconfig "github.com/google/knative-gcp/pkg/tracing" - "github.com/kelseyhightower/envconfig" "go.uber.org/zap" + "knative.dev/eventing/pkg/tracing" "knative.dev/pkg/logging" "knative.dev/pkg/metrics" "knative.dev/pkg/signals" + + metadataClient "github.com/google/knative-gcp/pkg/gclient/metadata" + . "github.com/google/knative-gcp/pkg/pubsub/adapter" + "github.com/google/knative-gcp/pkg/pubsub/adapter/context" + tracingconfig "github.com/google/knative-gcp/pkg/tracing" + "github.com/google/knative-gcp/pkg/utils" + "github.com/google/knative-gcp/pkg/utils/appcredentials" + "github.com/google/knative-gcp/pkg/utils/clients" + "github.com/kelseyhightower/envconfig" ) const ( - component = "PullSubscription::ReceiveAdapter" + component = "receive_adapter" + + // TODO make this configurable + maxConnectionsPerHost = 1000 ) +// TODO we should refactor this and reduce the number of environment variables. +// most of them are due to metrics, which has to change anyways. +type envConfig struct { + // Environment variable containing project id. + Project string `envconfig:"PROJECT_ID"` + + // Environment variable containing the sink URI. + Sink string `envconfig:"SINK_URI" required:"true"` + + // Environment variable containing the transformer URI. + Transformer string `envconfig:"TRANSFORMER_URI"` + + // Environment variable specifying the type of adapter to use. + AdapterType string `envconfig:"ADAPTER_TYPE"` + + // Topic is the environment variable containing the PubSub Topic being + // subscribed to's name. In the form that is unique within the project. + // E.g. 'laconia', not 'projects/my-gcp-project/topics/laconia'. + Topic string `envconfig:"PUBSUB_TOPIC_ID" required:"true"` + + // Subscription is the environment variable containing the name of the + // subscription to use. + Subscription string `envconfig:"PUBSUB_SUBSCRIPTION_ID" required:"true"` + + // ExtensionsBase64 is a based64 encoded json string of a map of + // CloudEvents extensions (key-value pairs) override onto the outbound + // event. + ExtensionsBase64 string `envconfig:"K_CE_EXTENSIONS" required:"true"` + + // MetricsConfigJson is a json string of metrics.ExporterOptions. + // This is used to configure the metrics exporter options, the config is + // stored in a config map inside the controllers namespace and copied here. + MetricsConfigJson string `envconfig:"K_METRICS_CONFIG" required:"true"` + + // LoggingConfigJson is a json string of logging.Config. + // This is used to configure the logging config, the config is stored in + // a config map inside the controllers namespace and copied here. + LoggingConfigJson string `envconfig:"K_LOGGING_CONFIG" required:"true"` + + // TracingConfigJson is a JSON string of tracing.Config. This is used to configure tracing. The + // original config is stored in a ConfigMap inside the controller's namespace. Its value is + // copied here as a JSON string. + TracingConfigJson string `envconfig:"K_TRACING_CONFIG" required:"true"` + + // Environment variable containing the namespace. + Namespace string `envconfig:"NAMESPACE" required:"true"` + + // Environment variable containing the name. + Name string `envconfig:"NAME" required:"true"` + + // Environment variable containing the resource group. E.g., storages.events.cloud.google.com. + ResourceGroup string `envconfig:"RESOURCE_GROUP" default:"pullsubscriptions.internal.pubsub.cloud.google.com" required:"true"` +} + +// TODO try to use the common main from broker. func main() { + appcredentials.MustExistOrUnsetEnv() + flag.Parse() - startable := adapter.Adapter{} - if err := envconfig.Process("", &startable); err != nil { + var env envConfig + if err := envconfig.Process("", &env); err != nil { panic(fmt.Sprintf("Failed to process env var: %s", err)) } // Convert json logging.Config to logging.Config. - loggingConfig, err := logging.JsonToLoggingConfig(startable.LoggingConfigJson) + loggingConfig, err := logging.JsonToLoggingConfig(env.LoggingConfigJson) if err != nil { - fmt.Printf("[ERROR] filed to process logging config: %s", err.Error()) + fmt.Printf("Failed to process logging config: %s", err.Error()) // Use default logging config. if loggingConfig, err = logging.NewConfigFromMap(map[string]string{}); err != nil { // If this fails, there is no recovering. @@ -61,7 +124,7 @@ func main() { ctx := logging.WithLogger(signals.NewContext(), logger.Sugar()) // Convert json metrics.ExporterOptions to metrics.ExporterOptions. - metricsConfig, err := metrics.JsonToMetricsOptions(startable.MetricsConfigJson) + metricsConfig, err := metrics.JsonToMetricsOptions(env.MetricsConfigJson) if err != nil { logger.Error("Failed to process metrics options", zap.Error(err)) } @@ -72,7 +135,7 @@ func main() { } } - tracingConfig, err := tracingconfig.JSONToConfig(startable.TracingConfigJson) + tracingConfig, err := tracingconfig.JSONToConfig(env.TracingConfigJson) if err != nil { logger.Error("Failed to process tracing options", zap.Error(err)) } @@ -80,18 +143,45 @@ func main() { logger.Error("Failed to setup tracing", zap.Error(err), zap.Any("tracingConfig", tracingConfig)) } - if startable.Project == "" { - project, err := metadata.ProjectID() - if err != nil { - logger.Fatal("failed to find project id. ", zap.Error(err)) - } - startable.Project = project + projectID, err := utils.ProjectID(env.Project, metadataClient.NewDefaultMetadataClient()) + if err != nil { + logger.Fatal("Failed to retrieve project id", zap.Error(err)) } - logger.Info("Starting Pub/Sub Receive Adapter.", zap.Any("adapter", startable)) - if err := startable.Start(ctx); err != nil { - logger.Fatal("failed to start adapter: ", zap.Error(err)) + // Convert base64 encoded json map to extensions map. + extensions, err := utils.Base64ToMap(env.ExtensionsBase64) + if err != nil { + logger.Error("Failed to convert base64 extensions to map: %v", zap.Error(err)) + } + + ctx = context.WithProjectKey(ctx, projectID) + ctx = context.WithTopicKey(ctx, env.Topic) + ctx = context.WithSubscriptionKey(ctx, env.Subscription) + + logger.Info("Initializing adapter", zap.String("projectID", projectID), zap.String("topicID", env.Topic), zap.String("subscriptionID", env.Subscription)) + + adapter, err := InitializeAdapter( + ctx, + clients.ProjectID(projectID), + SubscriptionID(env.Subscription), + clients.MaxConnsPerHost(maxConnectionsPerHost), + Name(env.Name), + Namespace(env.Namespace), + ResourceGroup(env.ResourceGroup), + AdapterType(env.AdapterType), + SinkURI(env.Sink), + TransformerURI(env.Transformer), + extensions) + + if err != nil { + logger.Fatal("Unable to create adapter", zap.Error(err)) + } + + logger.Info("Starting Receive Adapter.", zap.String("projectID", projectID), zap.String("topicID", env.Topic), zap.String("subscriptionID", env.Subscription)) + if err := adapter.Start(ctx); err != nil { + logging.FromContext(ctx).Error("Adapter has stopped with error", zap.String("projectID", projectID), zap.String("topicID", env.Topic), zap.String("subscriptionID", env.Subscription), zap.Error(err)) } + } func flush(logger *zap.Logger) { diff --git a/cmd/pubsub/receive_adapter/wire.go b/cmd/pubsub/receive_adapter/wire.go new file mode 100644 index 0000000000..b598bd71cc --- /dev/null +++ b/cmd/pubsub/receive_adapter/wire.go @@ -0,0 +1,46 @@ +// +build wireinject + +/* +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 main + +import ( + "context" + + "github.com/google/knative-gcp/pkg/pubsub/adapter" + "github.com/google/knative-gcp/pkg/utils/clients" + + "github.com/google/wire" +) + +func InitializeAdapter( + ctx context.Context, + projectID clients.ProjectID, + subscription adapter.SubscriptionID, + maxConnsPerHost clients.MaxConnsPerHost, + name adapter.Name, + namespace adapter.Namespace, + resourceGroup adapter.ResourceGroup, + adapterType adapter.AdapterType, + sinkURI adapter.SinkURI, + transformerURI adapter.TransformerURI, + extensions map[string]string, +) (*adapter.Adapter, error) { + panic(wire.Build( + adapter.AdapterSet, + )) +} diff --git a/cmd/pubsub/receive_adapter/wire_gen.go b/cmd/pubsub/receive_adapter/wire_gen.go new file mode 100644 index 0000000000..cb85eccb43 --- /dev/null +++ b/cmd/pubsub/receive_adapter/wire_gen.go @@ -0,0 +1,29 @@ +// Code generated by Wire. DO NOT EDIT. + +//go:generate wire +//+build !wireinject + +package main + +import ( + "context" + "github.com/google/knative-gcp/pkg/pubsub/adapter" + "github.com/google/knative-gcp/pkg/utils/clients" +) + +// Injectors from wire.go: + +func InitializeAdapter(ctx context.Context, projectID clients.ProjectID, subscription adapter.SubscriptionID, maxConnsPerHost clients.MaxConnsPerHost, name adapter.Name, namespace adapter.Namespace, resourceGroup adapter.ResourceGroup, adapterType adapter.AdapterType, sinkURI adapter.SinkURI, transformerURI adapter.TransformerURI, extensions map[string]string) (*adapter.Adapter, error) { + client, err := clients.NewPubsubClient(ctx, projectID) + if err != nil { + return nil, err + } + pubsubSubscription := adapter.NewPubSubSubscription(ctx, client, subscription) + httpClient := clients.NewHTTPClient(ctx, maxConnsPerHost) + statsReporter, err := adapter.NewStatsReporter(name, namespace, resourceGroup) + if err != nil { + return nil, err + } + adapterAdapter := adapter.NewAdapter(ctx, pubsubSubscription, httpClient, statsReporter, sinkURI, transformerURI, adapterType, extensions) + return adapterAdapter, nil +} diff --git a/pkg/broker/handler/fanout.go b/pkg/broker/handler/fanout.go index d4924c453b..7e008c2839 100644 --- a/pkg/broker/handler/fanout.go +++ b/pkg/broker/handler/fanout.go @@ -176,7 +176,6 @@ func (p *FanoutPool) SyncOnce(ctx context.Context) error { // Start the handler with broker key in context. hc.Start(handlerctx.WithBrokerKey(ctx, b.Key()), func(err error) { - // We will anyway get an error because of https://github.com/cloudevents/sdk-go/issues/470 if err != nil { logging.FromContext(ctx).Error("handler for broker has stopped with error", zap.String("broker", b.Key()), zap.Error(err)) } else { diff --git a/pkg/broker/ingress/handler.go b/pkg/broker/ingress/handler.go index c2a30d6c48..5b9cf36f6c 100644 --- a/pkg/broker/ingress/handler.go +++ b/pkg/broker/ingress/handler.go @@ -31,6 +31,7 @@ import ( "github.com/cloudevents/sdk-go/v2/protocol/http" "github.com/google/knative-gcp/pkg/metrics" "github.com/google/knative-gcp/pkg/tracing" + "github.com/google/knative-gcp/pkg/utils/clients" "github.com/google/wire" "go.opencensus.io/trace" "go.uber.org/zap" @@ -57,11 +58,11 @@ const ( // HandlerSet provides a handler with a real HTTPMessageReceiver and pubsub MultiTopicDecoupleSink. var HandlerSet wire.ProviderSet = wire.NewSet( NewHandler, - NewHTTPMessageReceiver, + clients.NewHTTPMessageReceiver, wire.Bind(new(HttpMessageReceiver), new(*kncloudevents.HttpMessageReceiver)), NewMultiTopicDecoupleSink, wire.Bind(new(DecoupleSink), new(*multiTopicDecoupleSink)), - NewPubsubClient, + clients.NewPubsubClient, metrics.NewIngressReporter, ) diff --git a/pkg/pubsub/adapter/adapter.go b/pkg/pubsub/adapter/adapter.go index 83af4cc101..60092c4e34 100644 --- a/pkg/pubsub/adapter/adapter.go +++ b/pkg/pubsub/adapter/adapter.go @@ -18,253 +18,202 @@ package adapter import ( "context" - "fmt" - + "errors" nethttp "net/http" + "time" - "go.opencensus.io/trace" "go.uber.org/zap" - cloudevents "github.com/cloudevents/sdk-go" - "github.com/cloudevents/sdk-go/pkg/cloudevents/transport" - "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http" - cepubsub "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub" - "github.com/google/knative-gcp/pkg/kncloudevents" + "cloud.google.com/go/pubsub" + "github.com/cloudevents/sdk-go/v2/binding" + ceclient "github.com/cloudevents/sdk-go/v2/client" + cehttp "github.com/cloudevents/sdk-go/v2/protocol/http" "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" - "github.com/google/knative-gcp/pkg/utils" - - "k8s.io/apimachinery/pkg/runtime/schema" - "knative.dev/pkg/logging" -) - -var ( - channelGVR = schema.GroupVersionResource{ - Group: "messaging.cloud.google.com", - Version: "v1alpha1", - Resource: "channels", - } + "go.opencensus.io/trace" + "knative.dev/eventing/pkg/logging" ) // Adapter implements the Pub/Sub adapter to deliver Pub/Sub messages from a // pre-existing topic/subscription to a Sink. type Adapter struct { - // Environment variable containing project id. - Project string `envconfig:"PROJECT_ID"` - - // Environment variable containing the sink URI. - Sink string `envconfig:"SINK_URI" required:"true"` - - // Environment variable containing the transformer URI. - Transformer string `envconfig:"TRANSFORMER_URI"` + // subscription is the pubsub subscription used to receive messages from pubsub. + subscription *pubsub.Subscription - // Environment variable specifying the type of adapter to use. - AdapterType string `envconfig:"ADAPTER_TYPE"` + // outbound is the client used to send events to. + outbound *nethttp.Client - // Topic is the environment variable containing the PubSub Topic being - // subscribed to's name. In the form that is unique within the project. - // E.g. 'laconia', not 'projects/my-gcp-project/topics/laconia'. - Topic string `envconfig:"PUBSUB_TOPIC_ID" required:"true"` + // sinkURI is the URI where to sink events to. + sinkURI string - // Subscription is the environment variable containing the name of the - // subscription to use. - Subscription string `envconfig:"PUBSUB_SUBSCRIPTION_ID" required:"true"` - - // ExtensionsBase64 is a based64 encoded json string of a map of - // CloudEvents extensions (key-value pairs) override onto the outbound - // event. - ExtensionsBase64 string `envconfig:"K_CE_EXTENSIONS" required:"true"` + // transformerURI is the URI for the transformer. + // Used for channels. + transformerURI string // extensions is the converted ExtensionsBased64 value. extensions map[string]string - // SendMode describes how the adapter sends events. - // One of [binary, structured, push]. Default: binary - SendMode converters.ModeType `envconfig:"SEND_MODE" default:"binary" required:"true"` - - // MetricsConfigJson is a json string of metrics.ExporterOptions. - // This is used to configure the metrics exporter options, the config is - // stored in a config map inside the controllers namespace and copied here. - MetricsConfigJson string `envconfig:"K_METRICS_CONFIG" required:"true"` - - // LoggingConfigJson is a json string of logging.Config. - // This is used to configure the logging config, the config is stored in - // a config map inside the controllers namespace and copied here. - LoggingConfigJson string `envconfig:"K_LOGGING_CONFIG" required:"true"` - - // TracingConfigJson is a JSON string of tracing.Config. This is used to configure tracing. The - // original config is stored in a ConfigMap inside the controller's namespace. Its value is - // copied here as a JSON string. - TracingConfigJson string `envconfig:"K_TRACING_CONFIG" required:"true"` - - // Environment variable containing the namespace. - Namespace string `envconfig:"NAMESPACE" required:"true"` - - // Environment variable containing the name. - Name string `envconfig:"NAME" required:"true"` - - // Environment variable containing the resource group. E.g., storages.events.cloud.google.com. - ResourceGroup string `envconfig:"RESOURCE_GROUP" default:"pullsubscriptions.pubsub.cloud.google.com" required:"true"` - - // inbound is the cloudevents client to use to receive events. - inbound cloudevents.Client - - // outbound is the cloudevents client to use to send events. - outbound cloudevents.Client - - // transformer is the cloudevents client to transform received events before sending. - transformer cloudevents.Client + adapterType string // reporter reports metrics to the configured backend. reporter StatsReporter -} -// Start starts the adapter. Note: Only call once, not thread safe. -func (a *Adapter) Start(ctx context.Context) error { - var err error + logger *zap.Logger +} - if a.SendMode == "" { - a.SendMode = converters.DefaultSendMode +// NewAdapter creates a new adapter. +func NewAdapter( + ctx context.Context, + subscription *pubsub.Subscription, + outbound *nethttp.Client, + reporter StatsReporter, + sinkURI SinkURI, + transformerURI TransformerURI, + adapterType AdapterType, + extensions map[string]string) *Adapter { + return &Adapter{ + subscription: subscription, + outbound: outbound, + reporter: reporter, + sinkURI: string(sinkURI), + transformerURI: string(transformerURI), + adapterType: string(adapterType), + extensions: extensions, + logger: logging.FromContext(ctx), } +} - // Convert base64 encoded json map to extensions map. - a.extensions, err = utils.Base64ToMap(a.ExtensionsBase64) - if err != nil { - fmt.Printf("[warn] failed to convert base64 extensions to map: %v", err) - } +func (a *Adapter) Start(ctx context.Context) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() - // Receive Events on Pub/Sub. - if a.inbound == nil { - if a.inbound, err = a.newPubSubClient(ctx); err != nil { - return fmt.Errorf("failed to create inbound cloudevent client: %w", err) - } - } + errCh := make(chan error, 1) + go func() { + errCh <- a.subscription.Receive(ctx, a.receive) + }() - // Send events on HTTP. - if a.outbound == nil { - if a.outbound, err = a.newHTTPClient(ctx, a.Sink); err != nil { - return fmt.Errorf("failed to create outbound cloudevent client: %w", err) - } + // Stop either if the adapter stops (sending to errCh) or if the context Done channel is closed. + select { + case err := <-errCh: + return err + case <-ctx.Done(): + break } - if a.reporter == nil { - a.reporter = NewStatsReporter() + // Done channel has been closed, we need to gracefully shutdown. The cancel() method will start its + // shutdown, if it hasn't finished in a reasonable amount of time, just return an error. + cancel() + select { + case err := <-errCh: + return err + case <-time.After(30 * time.Second): + return errors.New("timeout shutting down adapter") } +} - // Make the transformer client in case the TransformerURI has been set. - if a.Transformer != "" { - if a.transformer == nil { - if a.transformer, err = kncloudevents.NewDefaultClient(a.Transformer); err != nil { - return fmt.Errorf("failed to create transformer cloudevent client: %w", err) - } - } +func (a *Adapter) receive(ctx context.Context, msg *pubsub.Message) { + event, err := converters.Convert(ctx, msg, a.adapterType) + if err != nil { + a.logger.Debug("Failed to convert received message to an event, check the msg format: %w", zap.Error(err)) + // Ack the message so it won't be retried + msg.Ack() + return } - return a.inbound.StartReceiver(ctx, a.receive) -} - -func (a *Adapter) receive(ctx context.Context, event cloudevents.Event, resp *cloudevents.EventResponse) error { - logger := logging.FromContext(ctx).With(zap.Any("event.id", event.ID()), zap.Any("sink", a.Sink)) + // Apply CloudEvent override extensions to the outbound event. + for k, v := range a.extensions { + event.SetExtension(k, v) + } - // TODO Name and ResourceGroup might cause problems in the near future, as we might use a single receive-adapter - // for multiple source objects. Same with Namespace, when doing multi-tenancy. args := &ReportArgs{ - Name: a.Name, - Namespace: a.Namespace, - EventType: event.Type(), - EventSource: event.Source(), - ResourceGroup: a.ResourceGroup, + EventType: event.Type(), + EventSource: event.Source(), } - var err error + message := (*binding.EventMessage)(event) + // If a transformer has been configured, then transform the message. // Note that this path in the code will be executed when using the receive adapter as part of the underlying Channel // of a Broker. We currently set the TransformerURI to be the address of the Broker filter pod. - // TODO consider renaming transformer as it is confusing. - if a.transformer != nil { - transformedCTX, transformedEvent, err := a.transformer.Send(ctx, event) - rtctx := cloudevents.HTTPTransportContextFrom(transformedCTX) + // TODO consider renaming transformer as it is confusing. And see if we can get rid of this. + if a.transformerURI != "" { + resp, err := a.sendMsg(ctx, a.transformerURI, message) if err != nil { - logger.Errorf("error transforming cloud event %q", event.ID()) - a.reporter.ReportEventCount(args, rtctx.StatusCode) - return err + a.logger.Error("Failed to send message to transformer", zap.String("address", a.transformerURI), zap.Error(err)) + msg.Nack() + return + } + + defer func() { + if err := resp.Body.Close(); err != nil { + a.logger.Warn("Failed to close response body", zap.Error(err)) + } + }() + + a.reporter.ReportEventCount(args, resp.StatusCode) + + if resp.StatusCode/100 != 2 { + a.logger.Error("Event delivery failed", zap.Int("StatusCode", resp.StatusCode)) + msg.Nack() + return } - if transformedEvent == nil { + + respMsg := cehttp.NewMessageFromHttpResponse(resp) + if respMsg.ReadEncoding() == binding.EncodingUnknown { // This doesn't mean there was an error. E.g., the Broker filter pod might not return a response. - // Report the returned Status Code and return. - logger.Debugf("cloud event %q was not transformed", event.ID()) - a.reporter.ReportEventCount(args, rtctx.StatusCode) - return nil + msg.Ack() + return } - // Update the event with the transformed one. - event = *transformedEvent + + e, err := binding.ToEvent(ctx, respMsg) + if err != nil { + a.logger.Error("Failed to convert response message to event", + zap.Any("response", respMsg), zap.Error(err)) + msg.Ack() + return + } + + // TODO check if this is OK // Update the tracing information to use the span returned by the transformer. - ctx = trace.NewContext(ctx, trace.FromContext(transformedCTX)) - } + // ctx = trace.NewContext(ctx, trace.FromContext(transformedCTX)) + if span := trace.FromContext(ctx); span.IsRecordingEvents() { + span.Annotate(ceclient.EventTraceAttributes(e), + "Event reply", + ) + } - // Apply CloudEvent override extensions to the outbound event. - for k, v := range a.extensions { - event.SetExtension(k, v) + // Update the message with the transformed one. + message = (*binding.EventMessage)(e) } - // Send the event and report the count. - rctx, r, err := a.outbound.Send(ctx, event) - rtctx := cloudevents.HTTPTransportContextFrom(rctx) - a.reporter.ReportEventCount(args, rtctx.StatusCode) + resp, err := a.sendMsg(ctx, a.sinkURI, message) if err != nil { - return err - } else if r != nil { - resp.RespondWith(nethttp.StatusOK, r) + a.logger.Error("Failed to send message to sink", zap.String("address", a.sinkURI), zap.Error(err)) + msg.Nack() + return } - return nil -} -func (a *Adapter) convert(ctx context.Context, m transport.Message, err error) (*cloudevents.Event, error) { - logger := logging.FromContext(ctx) - logger.Debug("Converting event from transport.") + a.reporter.ReportEventCount(args, resp.StatusCode) - if msg, ok := m.(*cepubsub.Message); ok { - return converters.Convert(ctx, msg, a.SendMode, a.AdapterType) + if resp.StatusCode/100 != 2 { + a.logger.Error("Event delivery failed", zap.Int("StatusCode", resp.StatusCode)) + msg.Nack() + return } - return nil, err -} -func (a *Adapter) newPubSubClient(ctx context.Context) (cloudevents.Client, error) { - tOpts := []cepubsub.Option{ - cepubsub.WithProjectID(a.Project), - cepubsub.WithTopicID(a.Topic), - cepubsub.WithSubscriptionAndTopicID(a.Subscription, a.Topic), + if err := resp.Body.Close(); err != nil { + a.logger.Warn("Failed to close response body", zap.Error(err)) } - // Make a pubsub transport for the CloudEvents client. - t, err := cepubsub.New(ctx, tOpts...) - if err != nil { - return nil, err - } - - // Use the transport to make a new CloudEvents client. - return cloudevents.NewClient(t, - cloudevents.WithConverterFn(a.convert), - ) + msg.Ack() } -func (a *Adapter) newHTTPClient(ctx context.Context, target string) (cloudevents.Client, error) { - tOpts := []http.Option{ - cloudevents.WithTarget(target), - } - - switch a.SendMode { - case converters.Binary, converters.Push: - tOpts = append(tOpts, cloudevents.WithBinaryEncoding()) - case converters.Structured: - tOpts = append(tOpts, cloudevents.WithStructuredEncoding()) - } - - // Make an http transport for the CloudEvents client. - t, err := cloudevents.NewHTTPTransport(tOpts...) +func (a *Adapter) sendMsg(ctx context.Context, address string, msg binding.Message) (*nethttp.Response, error) { + req, err := nethttp.NewRequestWithContext(ctx, nethttp.MethodPost, address, nil) if err != nil { return nil, err } - - // Use the transport to make a new CloudEvents client. - return cloudevents.NewClient(t) + if err := cehttp.WriteRequest(ctx, msg, req); err != nil { + return nil, err + } + return a.outbound.Do(req) } diff --git a/pkg/pubsub/adapter/adapter_test.go b/pkg/pubsub/adapter/adapter_test.go index 96bfb9da79..41994c9b4d 100644 --- a/pkg/pubsub/adapter/adapter_test.go +++ b/pkg/pubsub/adapter/adapter_test.go @@ -16,412 +16,396 @@ limitations under the License. package adapter -import ( - "bytes" - "context" - "io" - "net/http" - "net/http/httptest" - "testing" - "cloud.google.com/go/pubsub" - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" - "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" +// TODO fix all - cloudevents "github.com/cloudevents/sdk-go" - cepubsub "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub" - pubsubcontext "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/context" -) - -type mockStatsReporter struct { - gotArgs *ReportArgs - gotCode int -} - -func (r *mockStatsReporter) ReportEventCount(args *ReportArgs, responseCode int) error { - r.gotArgs = args - r.gotCode = responseCode - return nil -} - -func TestStartAdapter(t *testing.T) { - t.Skipf("need to fix the error from call to newPubSubClient: %s", `pubsub: google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.`) - a := Adapter{ - Project: "proj", - Topic: "top", - Subscription: "sub", - Sink: "http://localhost:8081", - Transformer: "http://localhost:8080", - ExtensionsBase64: "eyJrZXkxIjoidmFsdWUxIiwia2V5MiI6InZhbHVlMiJ9Cg==", - } - // This test only does sanity checks to see if all fields are - // initialized. - // In reality, Start should be a blocking function. Here, it's not - // blocking because we expect it to fail as it shouldn't be able to - // connect to pubsub. - if err := a.Start(context.Background()); err == nil { - t.Fatal("adapter.Start got nil want error") - } - - if a.SendMode == "" { - t.Errorf("adapter.SendMode got %q want %q", a.SendMode, converters.DefaultSendMode) - } - if a.reporter == nil { - t.Error("adapter.reporter got nil want a StatsReporter") - } - if a.inbound == nil { - t.Error("adapter.inbound got nil want a cloudevents.Client") - } - if a.outbound == nil { - t.Error("adapter.outbound got nil want a cloudevents.Client") - } - if a.transformer == nil { - t.Error("adapter.transformer got nil want a cloudevents.Client") - } - wantExt := map[string]string{"key1": "value1", "key2": "value2"} - if !cmp.Equal(wantExt, a.extensions) { - t.Errorf("adapter.extensions got %v want %v", a.extensions, wantExt) - } -} - -func TestInboundConvert(t *testing.T) { - cases := []struct { - name string - ctx context.Context - message *cepubsub.Message - wantMessageFn func() *cloudevents.Event - wantErr bool - }{{ - name: "pubsub event", - ctx: pubsubcontext.WithTransportContext( - context.Background(), - pubsubcontext.NewTransportContext( - "proj", "topic", "sub", "test", - &pubsub.Message{ID: "abc"}, - ), - ), - message: &cepubsub.Message{ - Data: []byte("some data"), - Attributes: map[string]string{ - "schema": "http://example.com", - "key1": "value1", - }, - }, - wantMessageFn: func() *cloudevents.Event { - e := cloudevents.NewEvent(cloudevents.VersionV1) - e.SetID("abc") - e.SetSource(v1alpha1.CloudPubSubSourceEventSource("proj", "topic")) - e.SetDataContentType("application/octet-stream") - e.SetType(v1alpha1.CloudPubSubSourcePublish) - e.SetDataSchema("http://example.com") - e.SetExtension("knativecemode", string(converters.DefaultSendMode)) - e.Data = []byte("some data") - e.DataEncoded = true - e.SetExtension("key1", "value1") - return &e - }, - }, { - name: "storage event", - ctx: pubsubcontext.WithTransportContext( - context.Background(), - pubsubcontext.NewTransportContext( - "proj", "topic", "sub", "test", - &pubsub.Message{ID: "abc"}, - ), - ), - message: &cepubsub.Message{ - Data: []byte("some data"), - Attributes: map[string]string{ - "knative-gcp": "com.google.cloud.storage", - "bucketId": "my-bucket", - "objectId": "my-obj", - "key1": "value1", - "eventType": "OBJECT_FINALIZE", - }, - }, - wantMessageFn: func() *cloudevents.Event { - e := cloudevents.NewEvent(cloudevents.VersionV1) - e.SetID("abc") - e.SetSource(v1alpha1.CloudStorageSourceEventSource("my-bucket")) - e.SetSubject("my-obj") - e.SetDataContentType(*cloudevents.StringOfApplicationJSON()) - e.SetType("com.google.cloud.storage.object.finalize") - e.SetDataSchema("https://raw.githubusercontent.com/google/knative-gcp/master/schemas/storage/schema.json") - e.Data = []byte("some data") - e.DataEncoded = true - e.SetExtension("key1", "value1") - return &e - }, - }, { - name: "invalid storage event", - ctx: pubsubcontext.WithTransportContext( - context.Background(), - pubsubcontext.NewTransportContext( - "proj", "topic", "sub", "test", - &pubsub.Message{ID: "abc"}, - ), - ), - message: &cepubsub.Message{ - Data: []byte("some data"), - Attributes: map[string]string{ - "knative-gcp": "com.google.cloud.storage", - "key1": "value1", - "eventType": "OBJECT_FINALIZE", - }, - }, - wantMessageFn: func() *cloudevents.Event { return nil }, - wantErr: true, - }} - - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - a := Adapter{ - Project: "proj", - Topic: "top", - Subscription: "sub", - SendMode: converters.DefaultSendMode, - } - var err error - gotEvent, err := a.convert(tc.ctx, tc.message, err) - if (err != nil) != tc.wantErr { - t.Errorf("adapter.convert got error %v want error=%v", err, tc.wantErr) - } - if diff := cmp.Diff(tc.wantMessageFn(), gotEvent); diff != "" { - t.Errorf("adapter.convert got unexpeceted cloudevents.Event (-want +got) %s", diff) - } - }) - } -} - -func TestReceive(t *testing.T) { - cases := []struct { - name string - eventFn func() cloudevents.Event - returnStatus int - returnHeader http.Header - returnBody []byte - wantHeader http.Header - wantBody []byte - wantStatus int - wantEventFn func() *cloudevents.Event - wantReportArgs *ReportArgs - wantReportCode int - wantErr bool - isSource bool - }{{ - name: "success without responding event", - eventFn: func() cloudevents.Event { - e := cloudevents.NewEvent(cloudevents.VersionV1) - e.SetSource("source") - e.SetType("unit.testing") - e.SetID("abc") - e.SetDataContentType("application/json") - e.Data = []byte(`{"key":"value"}`) - return e - }, - returnStatus: http.StatusOK, - wantHeader: map[string][]string{ - "Ce-Id": {"abc"}, - "Ce-Source": {"source"}, - "Ce-Specversion": {"1.0"}, - "Ce-Type": {"unit.testing"}, - "Content-Length": {"15"}, - "Content-Type": {"application/json"}, - }, - wantBody: []byte(`{"key":"value"}`), - wantEventFn: func() *cloudevents.Event { return nil }, - wantReportArgs: &ReportArgs{ - EventSource: "source", - EventType: "unit.testing", - ResourceGroup: "channels.messaging.cloud.google.com", - }, - wantReportCode: 200, - }, { - name: "success without responding event and from source", - eventFn: func() cloudevents.Event { - e := cloudevents.NewEvent(cloudevents.VersionV1) - e.SetSource("source") - e.SetType("unit.testing") - e.SetID("abc") - e.SetDataContentType("application/json") - e.Data = []byte(`{"key":"value"}`) - return e - }, - returnStatus: http.StatusOK, - isSource: true, - wantHeader: map[string][]string{ - "Ce-Id": {"abc"}, - "Ce-Source": {"source"}, - "Ce-Specversion": {"1.0"}, - "Ce-Type": {"unit.testing"}, - "Content-Length": {"15"}, - "Content-Type": {"application/json"}, - }, - wantBody: []byte(`{"key":"value"}`), - wantEventFn: func() *cloudevents.Event { return nil }, - wantReportArgs: &ReportArgs{ - EventSource: "source", - EventType: "unit.testing", - ResourceGroup: "pubsub.events.cloud.google.com", - }, - wantReportCode: 200, - }, { - name: "success with responding event", - eventFn: func() cloudevents.Event { - e := cloudevents.NewEvent(cloudevents.VersionV1) - e.SetSource("source") - e.SetType("unit.testing") - e.SetID("abc") - e.SetDataContentType("application/json") - e.Data = []byte(`{"key":"value"}`) - return e - }, - returnStatus: http.StatusOK, - returnHeader: map[string][]string{ - "Ce-Id": {"def"}, - "Ce-Source": {"reply-source"}, - "Ce-Specversion": {"1.0"}, - "Ce-Type": {"unit.testing.reply"}, - "Content-Type": {"application/json"}, - }, - returnBody: []byte(`{"key2":"value2"}`), - wantHeader: map[string][]string{ - "Ce-Id": {"abc"}, - "Ce-Source": {"source"}, - "Ce-Specversion": {"1.0"}, - "Ce-Type": {"unit.testing"}, - "Content-Length": {"15"}, - "Content-Type": {"application/json"}, - }, - wantBody: []byte(`{"key":"value"}`), - wantEventFn: func() *cloudevents.Event { - e := cloudevents.NewEvent(cloudevents.VersionV1) - e.SetSource("reply-source") - e.SetType("unit.testing.reply") - e.SetID("def") - e.SetDataContentType("application/json") - e.Data = []byte(`{"key2":"value2"}`) - e.DataEncoded = true - return &e - }, - wantStatus: 200, - wantReportArgs: &ReportArgs{ - EventSource: "source", - EventType: "unit.testing", - ResourceGroup: "channels.messaging.cloud.google.com", - }, - wantReportCode: 200, - }, { - name: "receiver internal error", - eventFn: func() cloudevents.Event { - e := cloudevents.NewEvent(cloudevents.VersionV1) - e.SetSource("source") - e.SetType("unit.testing") - e.SetID("abc") - e.SetDataContentType("application/json") - e.Data = []byte(`{"key":"value"}`) - return e - }, - returnStatus: http.StatusInternalServerError, - wantHeader: map[string][]string{ - "Ce-Id": {"abc"}, - "Ce-Source": {"source"}, - "Ce-Specversion": {"1.0"}, - "Ce-Type": {"unit.testing"}, - "Content-Length": {"15"}, - "Content-Type": {"application/json"}, - }, - wantBody: []byte(`{"key":"value"}`), - wantEventFn: func() *cloudevents.Event { return nil }, - wantReportArgs: &ReportArgs{ - EventSource: "source", - EventType: "unit.testing", - ResourceGroup: "channels.messaging.cloud.google.com", - }, - wantReportCode: 500, - wantErr: true, - }} - - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - var gotHeader http.Header - var gotBody []byte - handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - gotHeader = req.Header - gotHeader.Del("Accept-Encoding") - gotHeader.Del("User-Agent") - b := bytes.NewBuffer(gotBody) - defer req.Body.Close() - io.Copy(b, req.Body) - gotBody = b.Bytes() - - for k, vs := range tc.returnHeader { - for _, v := range vs { - w.Header().Add(k, v) - } - } - w.WriteHeader(tc.returnStatus) - w.Write(tc.returnBody) - }) - server := httptest.NewServer(handler) - - r := &mockStatsReporter{} - var resourceGroup string - if tc.isSource { - resourceGroup = "pubsub.events.cloud.google.com" - } else { - resourceGroup = "channels.messaging.cloud.google.com" - } - a := Adapter{ - Project: "proj", - Topic: "topic", - Subscription: "sub", - SendMode: converters.Binary, - reporter: r, - ResourceGroup: resourceGroup, - } - - var err error - if a.outbound, err = a.newHTTPClient(context.Background(), server.URL); err != nil { - t.Fatalf("failed to to set adapter outbound to receive events: %v", err) - } - - var resp cloudevents.EventResponse - err = a.receive(context.Background(), tc.eventFn(), &resp) - - if (err != nil) != tc.wantErr { - t.Errorf("adapter.receiver got error %v want error %v", err, tc.wantErr) - } - - options := make([]cmp.Option, 0) - ignoreCeTraceparent := cmpopts.IgnoreMapEntries(func(n string, _ []string) bool { - return n == "Ce-Traceparent" - }) - options = append(options, ignoreCeTraceparent) - ignoreTraceParent := cmpopts.IgnoreMapEntries(func(n string, _ []string) bool { - return n == "Traceparent" - }) - options = append(options, ignoreTraceParent) - if diff := cmp.Diff(tc.wantHeader, gotHeader, options...); diff != "" { - t.Errorf("receiver got unexpected HTTP header (-want +got): %s", diff) - } - if !bytes.Equal(tc.wantBody, gotBody) { - t.Errorf("receiver got HTTP body %v want %v", string(gotBody), string(tc.wantBody)) - } - if resp.Status != tc.wantStatus { - t.Errorf("adapter.receiver got resp status %d want %d", resp.Status, tc.wantStatus) - } - if diff := cmp.Diff(tc.wantEventFn(), resp.Event); diff != "" { - t.Errorf("adapter.receiver got unexpected resp event (-want +got): %s", diff) - } - if diff := cmp.Diff(tc.wantReportArgs, r.gotArgs); diff != "" { - t.Errorf("stats reporter got unexpected args (-want +got): %s", diff) - } - if r.gotCode != tc.wantReportCode { - t.Errorf("stats reporter got status code %d want %d", r.gotCode, tc.wantReportCode) - } - }) - } -} +//type mockStatsReporter struct { +// gotArgs *ReportArgs +// gotCode int +//} +// +//func (r *mockStatsReporter) ReportEventCount(args *ReportArgs, responseCode int) error { +// r.gotArgs = args +// r.gotCode = responseCode +// return nil +//} +// +//func TestStartAdapter(t *testing.T) { +// t.Skipf("need to fix the error from call to newPubSubClient: %s", `pubsub: google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.`) +// a := Adapter{ +// Project: "proj", +// Topic: "top", +// Subscription: "sub", +// Sink: "http://localhost:8081", +// Transformer: "http://localhost:8080", +// ExtensionsBase64: "eyJrZXkxIjoidmFsdWUxIiwia2V5MiI6InZhbHVlMiJ9Cg==", +// } +// // This test only does sanity checks to see if all fields are +// // initialized. +// // In reality, Start should be a blocking function. Here, it's not +// // blocking because we expect it to fail as it shouldn't be able to +// // connect to pubsub. +// if err := a.Start(context.Background()); err == nil { +// t.Fatal("adapter.Start got nil want error") +// } +// +// if a.SendMode == "" { +// t.Errorf("adapter.SendMode got %q want %q", a.SendMode, converters.DefaultSendMode) +// } +// if a.reporter == nil { +// t.Error("adapter.reporter got nil want a StatsReporter") +// } +// if a.inbound == nil { +// t.Error("adapter.inbound got nil want a cloudevents.Client") +// } +// if a.outbound == nil { +// t.Error("adapter.outbound got nil want a cloudevents.Client") +// } +// if a.transformer == nil { +// t.Error("adapter.transformer got nil want a cloudevents.Client") +// } +// wantExt := map[string]string{"key1": "value1", "key2": "value2"} +// if !cmp.Equal(wantExt, a.extensions) { +// t.Errorf("adapter.extensions got %v want %v", a.extensions, wantExt) +// } +//} +// +//func TestInboundConvert(t *testing.T) { +// cases := []struct { +// name string +// ctx context.Context +// message *cepubsub.Message +// wantMessageFn func() *cloudevents.Event +// wantErr bool +// }{{ +// name: "pubsub event", +// ctx: pubsubcontext.WithTransportContext( +// context.Background(), +// pubsubcontext.NewTransportContext( +// "proj", "topic", "sub", "test", +// &pubsub.Message{ID: "abc"}, +// ), +// ), +// message: &cepubsub.Message{ +// Data: []byte("some data"), +// Attributes: map[string]string{ +// "schema": "http://example.com", +// "key1": "value1", +// }, +// }, +// wantMessageFn: func() *cloudevents.Event { +// e := cloudevents.NewEvent(cloudevents.VersionV1) +// e.SetID("abc") +// e.SetSource(v1alpha1.CloudPubSubSourceEventSource("proj", "topic")) +// e.SetDataContentType("application/octet-stream") +// e.SetType(v1alpha1.CloudPubSubSourcePublish) +// e.SetDataSchema("http://example.com") +// e.SetExtension("knativecemode", string(converters.DefaultSendMode)) +// e.Data = []byte("some data") +// e.DataEncoded = true +// e.SetExtension("key1", "value1") +// return &e +// }, +// }, { +// name: "storage event", +// ctx: pubsubcontext.WithTransportContext( +// context.Background(), +// pubsubcontext.NewTransportContext( +// "proj", "topic", "sub", "test", +// &pubsub.Message{ID: "abc"}, +// ), +// ), +// message: &cepubsub.Message{ +// Data: []byte("some data"), +// Attributes: map[string]string{ +// "knative-gcp": "com.google.cloud.storage", +// "bucketId": "my-bucket", +// "objectId": "my-obj", +// "key1": "value1", +// "eventType": "OBJECT_FINALIZE", +// }, +// }, +// wantMessageFn: func() *cloudevents.Event { +// e := cloudevents.NewEvent(cloudevents.VersionV1) +// e.SetID("abc") +// e.SetSource(v1alpha1.CloudStorageSourceEventSource("my-bucket")) +// e.SetSubject("my-obj") +// e.SetDataContentType(*cloudevents.StringOfApplicationJSON()) +// e.SetType("com.google.cloud.storage.object.finalize") +// e.SetDataSchema("https://raw.githubusercontent.com/google/knative-gcp/master/schemas/storage/schema.json") +// e.Data = []byte("some data") +// e.DataEncoded = true +// e.SetExtension("key1", "value1") +// return &e +// }, +// }, { +// name: "invalid storage event", +// ctx: pubsubcontext.WithTransportContext( +// context.Background(), +// pubsubcontext.NewTransportContext( +// "proj", "topic", "sub", "test", +// &pubsub.Message{ID: "abc"}, +// ), +// ), +// message: &cepubsub.Message{ +// Data: []byte("some data"), +// Attributes: map[string]string{ +// "knative-gcp": "com.google.cloud.storage", +// "key1": "value1", +// "eventType": "OBJECT_FINALIZE", +// }, +// }, +// wantMessageFn: func() *cloudevents.Event { return nil }, +// wantErr: true, +// }} +// +// for _, tc := range cases { +// t.Run(tc.name, func(t *testing.T) { +// a := Adapter{ +// Project: "proj", +// Topic: "top", +// Subscription: "sub", +// SendMode: converters.DefaultSendMode, +// } +// var err error +// gotEvent, err := a.convert(tc.ctx, tc.message, err) +// if (err != nil) != tc.wantErr { +// t.Errorf("adapter.convert got error %v want error=%v", err, tc.wantErr) +// } +// if diff := cmp.Diff(tc.wantMessageFn(), gotEvent); diff != "" { +// t.Errorf("adapter.convert got unexpeceted cloudevents.Event (-want +got) %s", diff) +// } +// }) +// } +//} +// +//func TestReceive(t *testing.T) { +// cases := []struct { +// name string +// eventFn func() cloudevents.Event +// returnStatus int +// returnHeader http.Header +// returnBody []byte +// wantHeader http.Header +// wantBody []byte +// wantStatus int +// wantEventFn func() *cloudevents.Event +// wantReportArgs *ReportArgs +// wantReportCode int +// wantErr bool +// isSource bool +// }{{ +// name: "success without responding event", +// eventFn: func() cloudevents.Event { +// e := cloudevents.NewEvent(cloudevents.VersionV1) +// e.SetSource("source") +// e.SetType("unit.testing") +// e.SetID("abc") +// e.SetDataContentType("application/json") +// e.Data = []byte(`{"key":"value"}`) +// return e +// }, +// returnStatus: http.StatusOK, +// wantHeader: map[string][]string{ +// "Ce-Id": {"abc"}, +// "Ce-Source": {"source"}, +// "Ce-Specversion": {"1.0"}, +// "Ce-Type": {"unit.testing"}, +// "Content-Length": {"15"}, +// "Content-Type": {"application/json"}, +// }, +// wantBody: []byte(`{"key":"value"}`), +// wantEventFn: func() *cloudevents.Event { return nil }, +// wantReportArgs: &ReportArgs{ +// EventSource: "source", +// EventType: "unit.testing", +// ResourceGroup: "channels.messaging.cloud.google.com", +// }, +// wantReportCode: 200, +// }, { +// name: "success without responding event and from source", +// eventFn: func() cloudevents.Event { +// e := cloudevents.NewEvent(cloudevents.VersionV1) +// e.SetSource("source") +// e.SetType("unit.testing") +// e.SetID("abc") +// e.SetDataContentType("application/json") +// e.Data = []byte(`{"key":"value"}`) +// return e +// }, +// returnStatus: http.StatusOK, +// isSource: true, +// wantHeader: map[string][]string{ +// "Ce-Id": {"abc"}, +// "Ce-Source": {"source"}, +// "Ce-Specversion": {"1.0"}, +// "Ce-Type": {"unit.testing"}, +// "Content-Length": {"15"}, +// "Content-Type": {"application/json"}, +// }, +// wantBody: []byte(`{"key":"value"}`), +// wantEventFn: func() *cloudevents.Event { return nil }, +// wantReportArgs: &ReportArgs{ +// EventSource: "source", +// EventType: "unit.testing", +// ResourceGroup: "pubsub.events.cloud.google.com", +// }, +// wantReportCode: 200, +// }, { +// name: "success with responding event", +// eventFn: func() cloudevents.Event { +// e := cloudevents.NewEvent(cloudevents.VersionV1) +// e.SetSource("source") +// e.SetType("unit.testing") +// e.SetID("abc") +// e.SetDataContentType("application/json") +// e.Data = []byte(`{"key":"value"}`) +// return e +// }, +// returnStatus: http.StatusOK, +// returnHeader: map[string][]string{ +// "Ce-Id": {"def"}, +// "Ce-Source": {"reply-source"}, +// "Ce-Specversion": {"1.0"}, +// "Ce-Type": {"unit.testing.reply"}, +// "Content-Type": {"application/json"}, +// }, +// returnBody: []byte(`{"key2":"value2"}`), +// wantHeader: map[string][]string{ +// "Ce-Id": {"abc"}, +// "Ce-Source": {"source"}, +// "Ce-Specversion": {"1.0"}, +// "Ce-Type": {"unit.testing"}, +// "Content-Length": {"15"}, +// "Content-Type": {"application/json"}, +// }, +// wantBody: []byte(`{"key":"value"}`), +// wantEventFn: func() *cloudevents.Event { +// e := cloudevents.NewEvent(cloudevents.VersionV1) +// e.SetSource("reply-source") +// e.SetType("unit.testing.reply") +// e.SetID("def") +// e.SetDataContentType("application/json") +// e.Data = []byte(`{"key2":"value2"}`) +// e.DataEncoded = true +// return &e +// }, +// wantStatus: 200, +// wantReportArgs: &ReportArgs{ +// EventSource: "source", +// EventType: "unit.testing", +// ResourceGroup: "channels.messaging.cloud.google.com", +// }, +// wantReportCode: 200, +// }, { +// name: "receiver internal error", +// eventFn: func() cloudevents.Event { +// e := cloudevents.NewEvent(cloudevents.VersionV1) +// e.SetSource("source") +// e.SetType("unit.testing") +// e.SetID("abc") +// e.SetDataContentType("application/json") +// e.Data = []byte(`{"key":"value"}`) +// return e +// }, +// returnStatus: http.StatusInternalServerError, +// wantHeader: map[string][]string{ +// "Ce-Id": {"abc"}, +// "Ce-Source": {"source"}, +// "Ce-Specversion": {"1.0"}, +// "Ce-Type": {"unit.testing"}, +// "Content-Length": {"15"}, +// "Content-Type": {"application/json"}, +// }, +// wantBody: []byte(`{"key":"value"}`), +// wantEventFn: func() *cloudevents.Event { return nil }, +// wantReportArgs: &ReportArgs{ +// EventSource: "source", +// EventType: "unit.testing", +// ResourceGroup: "channels.messaging.cloud.google.com", +// }, +// wantReportCode: 500, +// wantErr: true, +// }} +// +// for _, tc := range cases { +// t.Run(tc.name, func(t *testing.T) { +// var gotHeader http.Header +// var gotBody []byte +// handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { +// gotHeader = req.Header +// gotHeader.Del("Accept-Encoding") +// gotHeader.Del("User-Agent") +// b := bytes.NewBuffer(gotBody) +// defer req.Body.Close() +// io.Copy(b, req.Body) +// gotBody = b.Bytes() +// +// for k, vs := range tc.returnHeader { +// for _, v := range vs { +// w.Header().Add(k, v) +// } +// } +// w.WriteHeader(tc.returnStatus) +// w.Write(tc.returnBody) +// }) +// server := httptest.NewServer(handler) +// +// r := &mockStatsReporter{} +// var resourceGroup string +// if tc.isSource { +// resourceGroup = "pubsub.events.cloud.google.com" +// } else { +// resourceGroup = "channels.messaging.cloud.google.com" +// } +// a := Adapter{ +// Project: "proj", +// Topic: "topic", +// Subscription: "sub", +// SendMode: converters.Binary, +// reporter: r, +// ResourceGroup: resourceGroup, +// } +// +// var err error +// if a.outbound, err = a.newHTTPClient(context.Background(), server.URL); err != nil { +// t.Fatalf("failed to to set adapter outbound to receive events: %v", err) +// } +// +// var resp cloudevents.EventResponse +// err = a.receive(context.Background(), tc.eventFn(), &resp) +// +// if (err != nil) != tc.wantErr { +// t.Errorf("adapter.receiver got error %v want error %v", err, tc.wantErr) +// } +// +// options := make([]cmp.Option, 0) +// ignoreCeTraceparent := cmpopts.IgnoreMapEntries(func(n string, _ []string) bool { +// return n == "Ce-Traceparent" +// }) +// options = append(options, ignoreCeTraceparent) +// ignoreTraceParent := cmpopts.IgnoreMapEntries(func(n string, _ []string) bool { +// return n == "Traceparent" +// }) +// options = append(options, ignoreTraceParent) +// if diff := cmp.Diff(tc.wantHeader, gotHeader, options...); diff != "" { +// t.Errorf("receiver got unexpected HTTP header (-want +got): %s", diff) +// } +// if !bytes.Equal(tc.wantBody, gotBody) { +// t.Errorf("receiver got HTTP body %v want %v", string(gotBody), string(tc.wantBody)) +// } +// if resp.Status != tc.wantStatus { +// t.Errorf("adapter.receiver got resp status %d want %d", resp.Status, tc.wantStatus) +// } +// if diff := cmp.Diff(tc.wantEventFn(), resp.Event); diff != "" { +// t.Errorf("adapter.receiver got unexpected resp event (-want +got): %s", diff) +// } +// if diff := cmp.Diff(tc.wantReportArgs, r.gotArgs); diff != "" { +// t.Errorf("stats reporter got unexpected args (-want +got): %s", diff) +// } +// if r.gotCode != tc.wantReportCode { +// t.Errorf("stats reporter got status code %d want %d", r.gotCode, tc.wantReportCode) +// } +// }) +// } +//} diff --git a/pkg/pubsub/adapter/context/errs.go b/pkg/pubsub/adapter/context/errs.go new file mode 100644 index 0000000000..553e68c46a --- /dev/null +++ b/pkg/pubsub/adapter/context/errs.go @@ -0,0 +1,25 @@ +/* +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 context + +import "errors" + +var ( + ErrProjectKeyNotPresent = errors.New("project key not present in the context") + ErrSubscriptionKeyNotPresent = errors.New("subscription key not present in the context") + ErrTopicKeyNotPresent = errors.New("topic key not present in the context") +) diff --git a/pkg/pubsub/adapter/context/project.go b/pkg/pubsub/adapter/context/project.go new file mode 100644 index 0000000000..78670e2181 --- /dev/null +++ b/pkg/pubsub/adapter/context/project.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 context + +import ( + "context" +) + +// The key used to store/retrieve the project in the context. +type projectKey struct{} + +// WithProjectKey sets a project key in the context. +func WithProjectKey(ctx context.Context, key string) context.Context { + return context.WithValue(ctx, projectKey{}, key) +} + +// GetProjectKey gets the project key from the context. +func GetProjectKey(ctx context.Context) (string, error) { + untyped := ctx.Value(projectKey{}) + if untyped == nil { + return "", ErrProjectKeyNotPresent + } + return untyped.(string), nil +} diff --git a/pkg/pubsub/adapter/context/project_test.go b/pkg/pubsub/adapter/context/project_test.go new file mode 100644 index 0000000000..7b7dc5e868 --- /dev/null +++ b/pkg/pubsub/adapter/context/project_test.go @@ -0,0 +1,39 @@ +/* +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 context + +import ( + "context" + "testing" +) + +func TestProjectKey(t *testing.T) { + _, err := GetProjectKey(context.Background()) + if err != ErrProjectKeyNotPresent { + t.Errorf("error from GetProjectKey got=%v, want=%v", err, ErrProjectKeyNotPresent) + } + + wantKey := "key" + ctx := WithProjectKey(context.Background(), wantKey) + gotKey, err := GetProjectKey(ctx) + if err != nil { + t.Errorf("unexpected error from GetProjectKey: %v", err) + } + if gotKey != wantKey { + t.Errorf("topic key from context got=%s, want=%s", gotKey, wantKey) + } +} diff --git a/pkg/pubsub/adapter/context/subscription.go b/pkg/pubsub/adapter/context/subscription.go new file mode 100644 index 0000000000..a63902b3ae --- /dev/null +++ b/pkg/pubsub/adapter/context/subscription.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 context + +import ( + "context" +) + +// The key used to store/retrieve the subscription in the context. +type subscriptionKey struct{} + +// WithSubscriptionKey sets a subscription key in the context. +func WithSubscriptionKey(ctx context.Context, key string) context.Context { + return context.WithValue(ctx, subscriptionKey{}, key) +} + +// GetSubscriptionKey gets the subscription key from the context. +func GetSubscriptionKey(ctx context.Context) (string, error) { + untyped := ctx.Value(subscriptionKey{}) + if untyped == nil { + return "", ErrSubscriptionKeyNotPresent + } + return untyped.(string), nil +} diff --git a/pkg/pubsub/adapter/context/subscription_test.go b/pkg/pubsub/adapter/context/subscription_test.go new file mode 100644 index 0000000000..270304b4ba --- /dev/null +++ b/pkg/pubsub/adapter/context/subscription_test.go @@ -0,0 +1,39 @@ +/* +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 context + +import ( + "context" + "testing" +) + +func TestSubscriptionKey(t *testing.T) { + _, err := GetSubscriptionKey(context.Background()) + if err != ErrSubscriptionKeyNotPresent { + t.Errorf("error from GetSubscriptionKey got=%v, want=%v", err, ErrSubscriptionKeyNotPresent) + } + + wantKey := "key" + ctx := WithSubscriptionKey(context.Background(), wantKey) + gotKey, err := GetSubscriptionKey(ctx) + if err != nil { + t.Errorf("unexpected error from GetSubscriptionKey: %v", err) + } + if gotKey != wantKey { + t.Errorf("topic key from context got=%s, want=%s", gotKey, wantKey) + } +} diff --git a/pkg/pubsub/adapter/context/topic.go b/pkg/pubsub/adapter/context/topic.go new file mode 100644 index 0000000000..cd568cb894 --- /dev/null +++ b/pkg/pubsub/adapter/context/topic.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 context + +import ( + "context" +) + +// The key used to store/retrieve the topic in the context. +type topicKey struct{} + +// WithTopicKey sets a topic key in the context. +func WithTopicKey(ctx context.Context, key string) context.Context { + return context.WithValue(ctx, topicKey{}, key) +} + +// GetTopicKey gets the topic key from the context. +func GetTopicKey(ctx context.Context) (string, error) { + untyped := ctx.Value(topicKey{}) + if untyped == nil { + return "", ErrTopicKeyNotPresent + } + return untyped.(string), nil +} diff --git a/pkg/pubsub/adapter/context/topic_test.go b/pkg/pubsub/adapter/context/topic_test.go new file mode 100644 index 0000000000..9b5b8f0045 --- /dev/null +++ b/pkg/pubsub/adapter/context/topic_test.go @@ -0,0 +1,39 @@ +/* +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 context + +import ( + "context" + "testing" +) + +func TestTopicKey(t *testing.T) { + _, err := GetTopicKey(context.Background()) + if err != ErrTopicKeyNotPresent { + t.Errorf("error from GetTopicKey got=%v, want=%v", err, ErrTopicKeyNotPresent) + } + + wantKey := "key" + ctx := WithTopicKey(context.Background(), wantKey) + gotKey, err := GetTopicKey(ctx) + if err != nil { + t.Errorf("unexpected error from GetTopicKey: %v", err) + } + if gotKey != wantKey { + t.Errorf("topic key from context got=%s, want=%s", gotKey, wantKey) + } +} diff --git a/pkg/pubsub/adapter/converters/auditlogs.go b/pkg/pubsub/adapter/converters/auditlogs.go index c06a8d4124..8556f3c5f5 100644 --- a/pkg/pubsub/adapter/converters/auditlogs.go +++ b/pkg/pubsub/adapter/converters/auditlogs.go @@ -26,8 +26,6 @@ import ( "regexp" "strings" - cloudevents "github.com/cloudevents/sdk-go" - cepubsub "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub" "github.com/golang/protobuf/jsonpb" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes" @@ -35,7 +33,9 @@ import ( auditpb "google.golang.org/genproto/googleapis/cloud/audit" logpb "google.golang.org/genproto/googleapis/logging/v2" - "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" + "cloud.google.com/go/pubsub" + cev2 "github.com/cloudevents/sdk-go/v2" + "github.com/google/knative-gcp/pkg/apis/events/v1beta1" ) const ( @@ -103,10 +103,7 @@ func resolveAnyUnknowns(typeURL string) (proto.Message, error) { return reflect.New(mt.Elem()).Interface().(proto.Message), nil } -func convertCloudAuditLogs(ctx context.Context, msg *cepubsub.Message, sendMode ModeType) (*cloudevents.Event, error) { - if msg == nil { - return nil, fmt.Errorf("nil pubsub message") - } +func convertCloudAuditLogs(ctx context.Context, msg *pubsub.Message) (*cev2.Event, error) { entry := logpb.LogEntry{} if err := jsonpbUnmarshaller.Unmarshal(bytes.NewReader(msg.Data), &entry); err != nil { return nil, fmt.Errorf("failed to decode LogEntry: %w", err) @@ -118,16 +115,15 @@ func convertCloudAuditLogs(ctx context.Context, msg *cepubsub.Message, sendMode } // Make a new event and convert the message payload. - event := cloudevents.NewEvent(cloudevents.VersionV1) - event.SetID(v1alpha1.CloudAuditLogsSourceEventID(entry.InsertId, entry.LogName, ptypes.TimestampString(entry.Timestamp))) + event := cev2.NewEvent(cev2.VersionV1) + event.SetID(v1beta1.CloudAuditLogsSourceEventID(entry.InsertId, entry.LogName, ptypes.TimestampString(entry.Timestamp))) if timestamp, err := ptypes.Timestamp(entry.Timestamp); err != nil { return nil, fmt.Errorf("invalid LogEntry timestamp: %w", err) } else { event.SetTime(timestamp) } - event.SetData(msg.Data) + event.SetData(cev2.ApplicationJSON, msg.Data) event.SetDataSchema(logEntrySchema) - event.SetDataContentType(cloudevents.ApplicationJSON) switch payload := entry.Payload.(type) { case *logpb.LogEntry_ProtoPayload: @@ -137,8 +133,8 @@ func convertCloudAuditLogs(ctx context.Context, msg *cepubsub.Message, sendMode } switch proto := unpacked.Message.(type) { case *auditpb.AuditLog: - event.SetType(v1alpha1.CloudAuditLogsSourceEvent) - event.SetSource(v1alpha1.CloudAuditLogsSourceEventSource(proto.ServiceName, parentResource)) + event.SetType(v1beta1.CloudAuditLogsSourceEvent) + event.SetSource(v1beta1.CloudAuditLogsSourceEventSource(proto.ServiceName, parentResource)) event.SetSubject(proto.ResourceName) event.SetExtension(serviceNameExtension, proto.ServiceName) event.SetExtension(methodNameExtension, proto.MethodName) diff --git a/pkg/pubsub/adapter/converters/auditlogs_test.go b/pkg/pubsub/adapter/converters/auditlogs_test.go index 0e486a0654..ffbb08fbe3 100644 --- a/pkg/pubsub/adapter/converters/auditlogs_test.go +++ b/pkg/pubsub/adapter/converters/auditlogs_test.go @@ -22,13 +22,12 @@ import ( "testing" "time" - "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" - - cepubsub "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub" + "cloud.google.com/go/pubsub" "github.com/golang/protobuf/jsonpb" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/timestamp" "github.com/google/go-cmp/cmp" + "github.com/google/knative-gcp/pkg/apis/events/v1beta1" auditpb "google.golang.org/genproto/googleapis/cloud/audit" logpb "google.golang.org/genproto/googleapis/logging/v2" "google.golang.org/protobuf/testing/protocmp" @@ -73,22 +72,22 @@ func TestConvertAuditLog(t *testing.T) { if err := new(jsonpb.Marshaler).Marshal(&buf, &logEntry); err != nil { t.Fatalf("Failed to marshal AuditLog pb: %v", err) } - msg := cepubsub.Message{ + msg := pubsub.Message{ Data: buf.Bytes(), } - e, err := Convert(context.Background(), &msg, "", CloudAuditLogsConverter) + e, err := Convert(context.Background(), &msg, CloudAuditLogsConverter) if err != nil { t.Fatalf("conversion failed: %v", err) } - if id := v1alpha1.CloudAuditLogsSourceEventID(insertID, logName, testTs); e.ID() != id { + if id := v1beta1.CloudAuditLogsSourceEventID(insertID, logName, testTs); e.ID() != id { t.Errorf("ID '%s' != '%s'", e.ID(), id) } if !e.Time().Equal(testTime) { t.Errorf("Time '%v' != '%v'", e.Time(), testTime) } - if want := v1alpha1.CloudAuditLogsSourceEventSource("test-service-name", "projects/test-project"); e.Source() != want { + if want := v1beta1.CloudAuditLogsSourceEventSource("test-service-name", "projects/test-project"); e.Source() != want { t.Errorf("Source %q != %q", e.Source(), want) } if e.Type() != "com.google.cloud.auditlog.event" { @@ -97,18 +96,16 @@ func TestConvertAuditLog(t *testing.T) { if want := "test-resource-name"; e.Subject() != want { t.Errorf("Subject %q != %q", e.Subject(), want) } - if data, err := e.DataBytes(); err != nil { - t.Errorf("Unable to get event data: %q", err) + + var actualLogEntry logpb.LogEntry + if err = jsonpb.Unmarshal(bytes.NewReader(e.Data()), &actualLogEntry); err != nil { + t.Errorf("Unable to unmarshal event data to LogEntry: %q", err) } else { - var actualLogEntry logpb.LogEntry - if err = jsonpb.Unmarshal(bytes.NewReader(data), &actualLogEntry); err != nil { - t.Errorf("Unable to unmarshal event data to LogEntry: %q", err) - } else { - if diff := cmp.Diff(logEntry, actualLogEntry, protocmp.Transform()); diff != "" { - t.Errorf("unexpected LogEntry (-want, +got) = %v", diff) - } + if diff := cmp.Diff(logEntry, actualLogEntry, protocmp.Transform()); diff != "" { + t.Errorf("unexpected LogEntry (-want, +got) = %v", diff) } } + wantExtensions := map[string]interface{}{ "servicename": "test-service-name", "methodname": "test-method-name", @@ -143,11 +140,11 @@ func TestConvertTextPayload(t *testing.T) { if err := new(jsonpb.Marshaler).Marshal(&buf, &logEntry); err != nil { t.Fatalf("Failed to marshal AuditLog pb: %v", err) } - msg := cepubsub.Message{ + msg := pubsub.Message{ Data: buf.Bytes(), } - _, err = Convert(context.Background(), &msg, "", CloudAuditLogsConverter) + _, err = Convert(context.Background(), &msg, CloudAuditLogsConverter) if err == nil { t.Errorf("Expected error when converting non-AuditLog LogEntry.") diff --git a/pkg/pubsub/adapter/converters/build.go b/pkg/pubsub/adapter/converters/build.go index dde311c624..da09db9780 100644 --- a/pkg/pubsub/adapter/converters/build.go +++ b/pkg/pubsub/adapter/converters/build.go @@ -20,12 +20,10 @@ import ( "context" "errors" - cloudevents "github.com/cloudevents/sdk-go" - . "github.com/cloudevents/sdk-go/pkg/cloudevents" - cepubsub "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub" - pubsubcontext "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/context" - - "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" + "cloud.google.com/go/pubsub" + cev2 "github.com/cloudevents/sdk-go/v2" + "github.com/google/knative-gcp/pkg/apis/events/v1beta1" + . "github.com/google/knative-gcp/pkg/pubsub/adapter/context" ) const ( @@ -33,44 +31,33 @@ const ( buildSchemaUrl = "https://raw.githubusercontent.com/google/knative-gcp/master/schemas/build/schema.json" ) -func convertCloudBuild(ctx context.Context, msg *cepubsub.Message, sendMode ModeType) (*cloudevents.Event, error) { - tx := pubsubcontext.TransportContextFrom(ctx) - // Make a new event and convert the message payload. - event := cloudevents.NewEvent(cloudevents.VersionV1) - event.SetID(tx.ID) - event.SetTime(tx.PublishTime) - // We do not know the content type and we do not want to inspect the payload, - // thus we set this generic one. - event.SetDataContentType(cloudevents.ApplicationJSON) - event.SetType(v1alpha1.CloudBuildSourceEvent) +func convertCloudBuild(ctx context.Context, msg *pubsub.Message) (*cev2.Event, error) { + event := cev2.NewEvent(cev2.VersionV1) + event.SetID(msg.ID) + event.SetTime(msg.PublishTime) + event.SetType(v1beta1.CloudBuildSourceEvent) event.SetDataSchema(buildSchemaUrl) + project, err := GetProjectKey(ctx) + if err != nil { + return nil, err + } + // Set the source and subject if it comes as an attribute. - if buildId, ok := msg.Attributes[v1alpha1.CloudBuildSourceBuildId]; !ok { + if buildId, ok := msg.Attributes[v1beta1.CloudBuildSourceBuildId]; !ok { return nil, errors.New("received event did not have buildId") } else { - event.SetSource(v1alpha1.CloudBuildSourceEventSource(tx.Project, buildId)) + event.SetSource(v1beta1.CloudBuildSourceEventSource(project, buildId)) } - if buildStatus, ok := msg.Attributes[v1alpha1.CloudBuildSourceBuildStatus]; !ok { + if buildStatus, ok := msg.Attributes[v1beta1.CloudBuildSourceBuildStatus]; !ok { return nil, errors.New("received event did not have build status") } else { event.SetSubject(buildStatus) } - // Set the mode to be an extension attribute. - event.SetExtension("knativecemode", string(sendMode)) - event.Data = msg.Data - event.DataEncoded = true - // Attributes are extensions. - if msg.Attributes != nil && len(msg.Attributes) > 0 { - for k, v := range msg.Attributes { - // CloudEvents v1.0 attributes MUST consist of lower-case letters ('a' to 'z') or digits ('0' to '9') as per - // the spec. It's not even possible for a conformant transport to allow non-base36 characters. - // Note `SetExtension` will make it lowercase so only `IsAlphaNumeric` needs to be checked here. - if IsAlphaNumeric(k) { - event.SetExtension(k, v) - } - } + if err := event.SetData(cev2.ApplicationJSON, msg); err != nil { + return nil, err } + return &event, nil } diff --git a/pkg/pubsub/adapter/converters/build_test.go b/pkg/pubsub/adapter/converters/build_test.go index 4ddedd2ba9..ae91c37b6d 100644 --- a/pkg/pubsub/adapter/converters/build_test.go +++ b/pkg/pubsub/adapter/converters/build_test.go @@ -18,14 +18,12 @@ package converters import ( "context" "testing" + "time" "cloud.google.com/go/pubsub" - - cloudevents "github.com/cloudevents/sdk-go" - cepubsub "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub" - pubsubcontext "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/context" - "github.com/google/go-cmp/cmp" - "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" + cev2 "github.com/cloudevents/sdk-go/v2" + "github.com/google/knative-gcp/pkg/apis/events/v1beta1" + . "github.com/google/knative-gcp/pkg/pubsub/adapter/context" ) const ( @@ -33,18 +31,23 @@ const ( buildStatus = "SUCCESS" ) +var ( + buildPublishTime = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) +) + func TestConvertCloudBuild(t *testing.T) { tests := []struct { name string - message *cepubsub.Message - sendMode ModeType - wantEventFn func() *cloudevents.Event + message *pubsub.Message + wantEventFn func() *cev2.Event wantErr bool }{{ - name: "valid attributes", - message: &cepubsub.Message{ - Data: []byte("test data"), + name: "valid event", + message: &pubsub.Message{ + ID: "id", + PublishTime: buildPublishTime, + Data: []byte("test data"), Attributes: map[string]string{ "buildId": buildID, "status": buildStatus, @@ -52,88 +55,83 @@ func TestConvertCloudBuild(t *testing.T) { "attribute2": "value2", }, }, - sendMode: Binary, - wantEventFn: func() *cloudevents.Event { + wantEventFn: func() *cev2.Event { return buildCloudEvent(map[string]string{ - "buildId": buildID, - "status": buildStatus, - "attribute1": "value1", - "attribute2": "value2", + "buildId": buildID, + "status": buildStatus, }, buildID, buildStatus) }, }, { name: "no buildId attributes", - message: &cepubsub.Message{ + message: &pubsub.Message{ Data: []byte("test data"), Attributes: map[string]string{ "status": buildStatus, }, }, - sendMode: Binary, - wantErr: true, + wantErr: true, }, { name: "no buildStatus attributes", - message: &cepubsub.Message{ + message: &pubsub.Message{ Data: []byte("test data"), Attributes: map[string]string{ "buildId": buildID, }, }, - sendMode: Binary, - wantErr: true, + wantErr: true, }, { name: "no attributes", - message: &cepubsub.Message{ + message: &pubsub.Message{ Data: []byte("test data"), Attributes: map[string]string{}, }, - sendMode: Binary, - wantErr: true, + wantErr: true, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - ctx := pubsubcontext.WithTransportContext(context.TODO(), pubsubcontext.NewTransportContext( - "testproject", - "testtopic", - "testsubscription", - "testmethod", - &pubsub.Message{ - ID: "id", - }, - )) - - gotEvent, err := Convert(ctx, test.message, test.sendMode, CloudBuildConverter) + ctx := WithProjectKey(context.Background(), "testproject") + gotEvent, err := Convert(ctx, test.message, CloudBuildConverter) if err != nil { if !test.wantErr { t.Errorf("converters.convertBuild got error %v want error=%v", err, test.wantErr) } } else { - if diff := cmp.Diff(test.wantEventFn(), gotEvent); diff != "" { - t.Errorf("converters.convertBuild got unexpeceted cloudevents.Event (-want +got) %s", diff) + if gotEvent.ID() != "id" { + t.Errorf("ID '%s' != '%s'", gotEvent.ID(), "id") + } + if !gotEvent.Time().Equal(buildPublishTime) { + t.Errorf("Time '%v' != '%v'", gotEvent.Time(), buildPublishTime) + } + if want := v1beta1.CloudBuildSourceEventSource("testproject", buildID); gotEvent.Source() != want { + t.Errorf("Source %q != %q", gotEvent.Source(), want) + } + if gotEvent.Type() != v1beta1.CloudBuildSourceEvent { + t.Errorf(`Type %q != %q`, gotEvent.Type(), v1beta1.CloudBuildSourceEvent) + } + if gotEvent.Subject() != buildStatus { + t.Errorf("Subject %q != %q", gotEvent.Subject(), buildStatus) + } + if gotEvent.DataSchema() != buildSchemaUrl { + t.Errorf("DataSchema %q != %q", gotEvent.DataSchema(), buildSchemaUrl) } } }) } } -func buildCloudEvent(extensions map[string]string, buildID, buildStatus string) *cloudevents.Event { - e := cloudevents.NewEvent(cloudevents.VersionV1) +func buildCloudEvent(extensions map[string]string, buildID, buildStatus string) *cev2.Event { + e := cev2.NewEvent(cev2.VersionV1) e.SetID("id") - e.SetSource(v1alpha1.CloudBuildSourceEventSource("testproject", buildID)) + e.SetTime(buildPublishTime) + e.SetSource(v1beta1.CloudBuildSourceEventSource("testproject", buildID)) e.SetSubject(buildStatus) - e.SetDataContentType(cloudevents.ApplicationJSON) - e.SetType(v1alpha1.CloudBuildSourceEvent) - e.SetExtension("knativecemode", string(Binary)) - e.SetDataSchema("https://raw.githubusercontent.com/google/knative-gcp/master/schemas/build/schema.json") - e.Data = []byte("test data") - e.DataEncoded = true - for k, v := range extensions { - e.SetExtension(k, v) - } + e.SetData(cev2.ApplicationJSON, []byte("test data")) + e.SetType(v1beta1.CloudBuildSourceEvent) + e.SetDataSchema(buildSchemaUrl) return &e } diff --git a/pkg/pubsub/adapter/converters/converters.go b/pkg/pubsub/adapter/converters/converters.go index 79d7d69fe0..37e0681a03 100644 --- a/pkg/pubsub/adapter/converters/converters.go +++ b/pkg/pubsub/adapter/converters/converters.go @@ -22,8 +22,8 @@ import ( "context" "fmt" - cloudevents "github.com/cloudevents/sdk-go" - cepubsub "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub" + "cloud.google.com/go/pubsub" + cev2 "github.com/cloudevents/sdk-go/v2" ) // ModeType is the type for mode enum. @@ -42,7 +42,7 @@ const ( KnativeGCPConverter = "knative-gcp" ) -type converterFn func(context.Context, *cepubsub.Message, ModeType) (*cloudevents.Event, error) +type converterFn func(context.Context, *pubsub.Message) (*cev2.Event, error) // converters is the map for handling Source specific event // conversions. For example, a GCS event will need to be @@ -64,14 +64,14 @@ func init() { // Convert converts a message off the pubsub format to a source specific if // there's a registered handler for the type in the converters map. // If there's no registered handler, a default Pubsub one will be used. -func Convert(ctx context.Context, msg *cepubsub.Message, sendMode ModeType, converterType string) (*cloudevents.Event, error) { +func Convert(ctx context.Context, msg *pubsub.Message, converterType string) (*cev2.Event, error) { if msg == nil { return nil, fmt.Errorf("nil pubsub message") } // Try the converterType, if specified. if converterType != "" { if c, ok := converters[converterType]; ok { - return c(ctx, msg, sendMode) + return c(ctx, msg) } } // Try the generic KnativeGCPConverter attribute, if present. @@ -79,11 +79,11 @@ func Convert(ctx context.Context, msg *cepubsub.Message, sendMode ModeType, conv if val, ok := msg.Attributes[KnativeGCPConverter]; ok { delete(msg.Attributes, KnativeGCPConverter) if c, ok := converters[val]; ok { - return c(ctx, msg, sendMode) + return c(ctx, msg) } } } // No converter, PubSub is the default one. - return convertPubSub(ctx, msg, sendMode) + return convertPubSub(ctx, msg) } diff --git a/pkg/pubsub/adapter/converters/pubsub.go b/pkg/pubsub/adapter/converters/pubsub.go index df0457ae27..8d020619b1 100644 --- a/pkg/pubsub/adapter/converters/pubsub.go +++ b/pkg/pubsub/adapter/converters/pubsub.go @@ -18,101 +18,47 @@ package converters import ( "context" - "time" - cloudevents "github.com/cloudevents/sdk-go" - . "github.com/cloudevents/sdk-go/pkg/cloudevents" - cepubsub "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub" - pubsubcontext "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/context" - "go.uber.org/zap" - "knative.dev/pkg/logging" - - "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" + "cloud.google.com/go/pubsub" + cev2 "github.com/cloudevents/sdk-go/v2" + "github.com/google/knative-gcp/pkg/apis/events/v1beta1" + . "github.com/google/knative-gcp/pkg/pubsub/adapter/context" ) -func convertPubSub(ctx context.Context, msg *cepubsub.Message, sendMode ModeType) (*cloudevents.Event, error) { - tx := pubsubcontext.TransportContextFrom(ctx) - // Make a new event and convert the message payload. - event := cloudevents.NewEvent(cloudevents.VersionV1) - event.SetID(tx.ID) - event.SetTime(tx.PublishTime) - event.SetSource(v1alpha1.CloudPubSubSourceEventSource(tx.Project, tx.Topic)) - event.SetType(v1alpha1.CloudPubSubSourcePublish) - // Set the schema if it comes as an attribute. - if val, ok := msg.Attributes["schema"]; ok { - delete(msg.Attributes, "schema") - event.SetDataSchema(val) - } - // Set the mode to be an extension attribute. - event.SetExtension("knativecemode", string(sendMode)) - // Setting the event Data for Pull format. If it's Push, it will be overwritten below. - // Setting it here to be able to leverage event.DataAs call below. - event.Data = msg.Data - event.DataEncoded = true - - logger := logging.FromContext(ctx).With(zap.Any("event.id", event.ID())) - // If send mode is Push, convert to Pub/Sub Push payload style. - if sendMode == Push { - // Set the content type to something that can be handled by codec.go. - event.SetDataContentType(cloudevents.ApplicationJSON) - msg := &PubSubMessage{ - ID: event.ID(), - Attributes: msg.Attributes, - PublishTime: event.Time(), - Data: event.Data, - } +func convertPubSub(ctx context.Context, msg *pubsub.Message) (*cev2.Event, error) { + event := cev2.NewEvent(cev2.VersionV1) + event.SetID(msg.ID) + event.SetTime(msg.PublishTime) - if err := event.SetData(&PushMessage{ - Subscription: tx.Subscription, - Message: msg, - }); err != nil { - logger.Desugar().Warn("Failed to set data.", zap.Error(err)) - } - } else { - // non-Push mode, attributes should be promoted to extensions. - // We do not know the content type and we do not want to inspect the payload, - // thus we set this generic one. - event.SetDataContentType("application/octet-stream") - if msg.Attributes != nil && len(msg.Attributes) > 0 { - for k, v := range msg.Attributes { - // CloudEvents v1.0 attributes MUST consist of lower-case letters ('a' to 'z') or digits ('0' to '9') as per - // the spec. It's not even possible for a conformant transport to allow non-base36 characters. - // Note `SetExtension` will make it lowercase so only `IsAlphaNumeric` needs to be checked here. - if IsAlphaNumeric(k) { - event.SetExtension(k, v) - } else { - logger.Desugar().Warn("Skipping attribute that is not a valid extension", zap.String(k, v)) - } - } - } + project, err := GetProjectKey(ctx) + if err != nil { + return nil, err + } + topic, err := GetTopicKey(ctx) + if err != nil { + return nil, err } - return &event, nil -} - -// PushMessage represents the format Pub/Sub uses to push events. -type PushMessage struct { - // Subscription is the subscription ID that received this Message. - Subscription string `json:"subscription"` - // Message holds the Pub/Sub message contents. - Message *PubSubMessage `json:"message,omitempty"` -} -// PubSubMessage matches the inner message format used by Push Subscriptions. -type PubSubMessage struct { - // ID identifies this message. This ID is assigned by the server and is - // populated for Messages obtained from a subscription. - // This field is read-only. - ID string `json:"messageId,omitempty"` + event.SetSource(v1beta1.CloudPubSubSourceEventSource(project, topic)) + event.SetType(v1beta1.CloudPubSubSourcePublish) - // Data is the actual data in the message. - Data interface{} `json:"data,omitempty"` + subscription, err := GetSubscriptionKey(ctx) + if err != nil { + return nil, err + } - // Attributes represents the key-value pairs the current message - // is labelled with. - Attributes map[string]string `json:"attributes,omitempty"` + pushMessage := &PushMessage{ + Subscription: subscription, + Message: &PubSubMessage{ + ID: msg.ID, + Attributes: msg.Attributes, + PublishTime: msg.PublishTime, + Data: msg.Data, + }, + } - // The time at which the message was published. This is populated by the - // server for Messages obtained from a subscription. - // This field is read-only. - PublishTime time.Time `json:"publishTime,omitempty"` + if err := event.SetData(cev2.ApplicationJSON, pushMessage); err != nil { + return nil, err + } + return &event, nil } diff --git a/pkg/pubsub/adapter/converters/pubsub_test.go b/pkg/pubsub/adapter/converters/pubsub_test.go index d502019256..7eea42f6c4 100644 --- a/pkg/pubsub/adapter/converters/pubsub_test.go +++ b/pkg/pubsub/adapter/converters/pubsub_test.go @@ -23,126 +23,54 @@ import ( "testing" "cloud.google.com/go/pubsub" - cloudevents "github.com/cloudevents/sdk-go" - cepubsub "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub" - pubsubcontext "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/context" + cev2 "github.com/cloudevents/sdk-go/v2" "github.com/google/go-cmp/cmp" - "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" + "github.com/google/knative-gcp/pkg/apis/events/v1beta1" + . "github.com/google/knative-gcp/pkg/pubsub/adapter/context" ) func TestConvertCloudPubSub(t *testing.T) { tests := []struct { name string - message *cepubsub.Message - sendMode ModeType - wantEventFn func() *cloudevents.Event + message *pubsub.Message + wantEventFn func() *cev2.Event wantErr bool }{{ - name: "valid attributes", - message: &cepubsub.Message{ - Data: []byte("test data"), - Attributes: map[string]string{ - "attribute1": "value1", - "attribute2": "value2", - }, - }, - sendMode: Binary, - wantEventFn: func() *cloudevents.Event { - return pubSubPullCloudEvent(map[string]string{ - "attribute1": "value1", - "attribute2": "value2", - }, "") - }, - }, { - name: "upper case attributes", - message: &cepubsub.Message{ - Data: []byte("test data"), - Attributes: map[string]string{ - "AttriBUte1": "value1", - "AttrIbuTe2": "value2", - }, - }, - sendMode: Binary, - wantEventFn: func() *cloudevents.Event { - return pubSubPullCloudEvent(map[string]string{ - "attribute1": "value1", - "attribute2": "value2", - }, "") - }, - }, { - name: "only setting valid alphanumeric attribute", - message: &cepubsub.Message{ - Data: []byte("test data"), - Attributes: map[string]string{ - "attribute1": "value1", - "Invalid-Attrib#$^": "value2", - }, - }, - sendMode: Binary, - wantEventFn: func() *cloudevents.Event { - return pubSubPullCloudEvent(map[string]string{ - "attribute1": "value1", - }, "") - }, - }, { - name: "schema as attribute", - message: &cepubsub.Message{ - Data: []byte("test data"), - Attributes: map[string]string{ - "attribute1": "value1", - "attribute2": "value2", - "schema": "schema_val", - }, - }, - sendMode: Binary, - wantEventFn: func() *cloudevents.Event { - return pubSubPullCloudEvent(map[string]string{ - "attribute1": "value1", - "attribute2": "value2", - }, "schema_val") - }, - }, { - name: "Push mode with non valid alphanumeric attribute", - message: &cepubsub.Message{ + name: "non valid alphanumeric attribute", + message: &pubsub.Message{ + ID: "id", Data: []byte("\"test data\""), // Data passed in quotes for it to be marshalled properly Attributes: map[string]string{ "attribute1": "value1", "Invalid-Attrib#$^": "value2", }, }, - sendMode: Push, - wantEventFn: func() *cloudevents.Event { - return pubSubPushCloudEvent(map[string]string{ + wantEventFn: func() *cev2.Event { + return pubSubCloudEvent(map[string]string{ "attribute1": "value1", "Invalid-Attrib#$^": "value2", }, "\"InRlc3QgZGF0YSI=\"") }, }, { - name: "Push mode with no attributes", - message: &cepubsub.Message{ + name: "no attributes", + message: &pubsub.Message{ + ID: "id", Data: []byte("\"test data\""), // Data passed in quotes for it to be marshalled properly Attributes: map[string]string{}, }, - sendMode: Push, - wantEventFn: func() *cloudevents.Event { - return pubSubPushCloudEvent(nil, "\"InRlc3QgZGF0YSI=\"") + wantEventFn: func() *cev2.Event { + return pubSubCloudEvent(nil, "\"InRlc3QgZGF0YSI=\"") }, }} for _, test := range tests { t.Run(test.name, func(t *testing.T) { - ctx := pubsubcontext.WithTransportContext(context.TODO(), pubsubcontext.NewTransportContext( - "testproject", - "testtopic", - "testsubscription", - "testmethod", - &pubsub.Message{ - ID: "id", - }, - )) + ctx := WithProjectKey(context.Background(), "testproject") + ctx = WithTopicKey(ctx, "testtopic") + ctx = WithSubscriptionKey(ctx, "testsubscription") - gotEvent, err := Convert(ctx, test.message, test.sendMode, "") + gotEvent, err := Convert(ctx, test.message, "") if err != nil { if !test.wantErr { t.Errorf("converters.convertPubsub got error %v want error=%v", err, test.wantErr) @@ -156,38 +84,18 @@ func TestConvertCloudPubSub(t *testing.T) { } } -func pubSubPullCloudEvent(extensions map[string]string, schema string) *cloudevents.Event { - e := cloudevents.NewEvent(cloudevents.VersionV1) - e.SetID("id") - e.SetSource(v1alpha1.CloudPubSubSourceEventSource("testproject", "testtopic")) - e.SetDataContentType("application/octet-stream") - e.SetType(v1alpha1.CloudPubSubSourcePublish) - e.SetExtension("knativecemode", string(Binary)) - e.Data = []byte("test data") - e.DataEncoded = true - for k, v := range extensions { - e.SetExtension(k, v) - } - if schema != "" { - e.SetDataSchema(schema) - } - return &e -} - -func pubSubPushCloudEvent(attributes map[string]string, data string) *cloudevents.Event { - e := cloudevents.NewEvent(cloudevents.VersionV1) +func pubSubCloudEvent(attributes map[string]string, data string) *cev2.Event { + e := cev2.NewEvent(cev2.VersionV1) e.SetID("id") - e.SetSource(v1alpha1.CloudPubSubSourceEventSource("testproject", "testtopic")) - e.SetDataContentType(cloudevents.ApplicationJSON) - e.SetType(v1alpha1.CloudPubSubSourcePublish) - e.SetExtension("knativecemode", string(Push)) + e.SetSource(v1beta1.CloudPubSubSourceEventSource("testproject", "testtopic")) at := "" if attributes != nil { ex, _ := json.Marshal(attributes) at = fmt.Sprintf(`"attributes":%s,`, ex) } s := fmt.Sprintf(`{"subscription":"testsubscription","message":{"messageId":"id","data":%s,%s"publishTime":"0001-01-01T00:00:00Z"}}`, data, at) - e.Data = []byte(s) - e.DataEncoded = true + e.SetData(cev2.ApplicationJSON, []byte(s)) + e.SetType(v1beta1.CloudPubSubSourcePublish) + e.DataBase64 = false return &e } diff --git a/pkg/pubsub/adapter/converters/push.go b/pkg/pubsub/adapter/converters/push.go new file mode 100644 index 0000000000..46e553f8ff --- /dev/null +++ b/pkg/pubsub/adapter/converters/push.go @@ -0,0 +1,31 @@ +package converters + +import "time" + +// PushMessage represents the format Pub/Sub uses to push events. +type PushMessage struct { + // Subscription is the subscription ID that received this Message. + Subscription string `json:"subscription"` + // Message holds the Pub/Sub message contents. + Message *PubSubMessage `json:"message,omitempty"` +} + +// PubSubMessage matches the inner message format used by Push Subscriptions. +type PubSubMessage struct { + // ID identifies this message. This ID is assigned by the server and is + // populated for Messages obtained from a subscription. + // This field is read-only. + ID string `json:"messageId,omitempty"` + + // Data is the actual data in the message. + Data interface{} `json:"data,omitempty"` + + // Attributes represents the key-value pairs the current message + // is labelled with. + Attributes map[string]string `json:"attributes,omitempty"` + + // The time at which the message was published. This is populated by the + // server for Messages obtained from a subscription. + // This field is read-only. + PublishTime time.Time `json:"publishTime,omitempty"` +} diff --git a/pkg/pubsub/adapter/converters/scheduler.go b/pkg/pubsub/adapter/converters/scheduler.go index 4c5093da3f..bc3c672922 100644 --- a/pkg/pubsub/adapter/converters/scheduler.go +++ b/pkg/pubsub/adapter/converters/scheduler.go @@ -20,65 +20,45 @@ import ( "context" "errors" - cloudevents "github.com/cloudevents/sdk-go" - . "github.com/cloudevents/sdk-go/pkg/cloudevents" - cepubsub "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub" - pubsubcontext "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/context" - - "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" + "github.com/google/knative-gcp/pkg/apis/events/v1beta1" "github.com/google/knative-gcp/pkg/reconciler/events/scheduler/resources" + + "cloud.google.com/go/pubsub" + cev2 "github.com/cloudevents/sdk-go/v2" ) const ( CloudSchedulerConverter = "com.google.cloud.scheduler" ) -func convertCloudScheduler(ctx context.Context, msg *cepubsub.Message, sendMode ModeType) (*cloudevents.Event, error) { - tx := pubsubcontext.TransportContextFrom(ctx) - // Make a new event and convert the message payload. - event := cloudevents.NewEvent(cloudevents.VersionV1) - event.SetID(tx.ID) - event.SetTime(tx.PublishTime) - // We do not know the content type and we do not want to inspect the payload, - // thus we set this generic one. - event.SetDataContentType("application/octet-stream") - event.SetType(v1alpha1.CloudSchedulerSourceExecute) - // Set the schema if it comes as an attribute. - if val, ok := msg.Attributes["schema"]; ok { - delete(msg.Attributes, "schema") - event.SetDataSchema(val) - } +func convertCloudScheduler(ctx context.Context, msg *pubsub.Message) (*cev2.Event, error) { + event := cev2.NewEvent(cev2.VersionV1) + event.SetID(msg.ID) + event.SetTime(msg.PublishTime) + event.SetType(v1beta1.CloudSchedulerSourceExecute) + // Set the source and subject if it comes as an attribute. - jobName, ok := msg.Attributes[v1alpha1.CloudSchedulerSourceJobName] + // We added this attributes so that we could identify the scheduler. + // We should remove them here. + jobName, ok := msg.Attributes[v1beta1.CloudSchedulerSourceJobName] if ok { - delete(msg.Attributes, v1alpha1.CloudSchedulerSourceJobName) + delete(msg.Attributes, v1beta1.CloudSchedulerSourceJobName) } else { return nil, errors.New("received event did not have jobName") } - schedulerName, ok := msg.Attributes[v1alpha1.CloudSchedulerSourceName] + schedulerName, ok := msg.Attributes[v1beta1.CloudSchedulerSourceName] if ok { - delete(msg.Attributes, v1alpha1.CloudSchedulerSourceName) + delete(msg.Attributes, v1beta1.CloudSchedulerSourceName) } else { return nil, errors.New("received event did not have schedulerName") } + parentName := resources.ExtractParentName(jobName) - event.SetSource(v1alpha1.CloudSchedulerSourceEventSource(parentName, schedulerName)) + event.SetSource(v1beta1.CloudSchedulerSourceEventSource(parentName, schedulerName)) event.SetSubject(resources.ExtractJobID(jobName)) - // Set the mode to be an extension attribute. - event.SetExtension("knativecemode", string(sendMode)) - event.Data = msg.Data - event.DataEncoded = true - // Attributes are extensions. - if msg.Attributes != nil && len(msg.Attributes) > 0 { - for k, v := range msg.Attributes { - // CloudEvents v1.0 attributes MUST consist of lower-case letters ('a' to 'z') or digits ('0' to '9') as per - // the spec. It's not even possible for a conformant transport to allow non-base36 characters. - // Note `SetExtension` will make it lowercase so only `IsAlphaNumeric` needs to be checked here. - if IsAlphaNumeric(k) { - event.SetExtension(k, v) - } - } + if err := event.SetData(cev2.ApplicationJSON, msg.Data); err != nil { + return nil, err } return &event, nil } diff --git a/pkg/pubsub/adapter/converters/scheduler_test.go b/pkg/pubsub/adapter/converters/scheduler_test.go index 6d068578db..82b15b3b2f 100644 --- a/pkg/pubsub/adapter/converters/scheduler_test.go +++ b/pkg/pubsub/adapter/converters/scheduler_test.go @@ -22,26 +22,24 @@ import ( "testing" "cloud.google.com/go/pubsub" - cloudevents "github.com/cloudevents/sdk-go" - cepubsub "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub" - pubsubcontext "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/context" "github.com/google/go-cmp/cmp" + "github.com/google/knative-gcp/pkg/apis/events/v1beta1" - "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" + cev2 "github.com/cloudevents/sdk-go/v2" ) func TestConvertCloudSchedulerSource(t *testing.T) { tests := []struct { name string - message *cepubsub.Message + message *pubsub.Message source string - sendMode ModeType - wantEventFn func() *cloudevents.Event + wantEventFn func() *cev2.Event wantErr string }{{ name: "valid attributes", - message: &cepubsub.Message{ + message: &pubsub.Message{ + ID: "id", Data: []byte("test data"), Attributes: map[string]string{ "knative-gcp": "com.google.cloud.scheduler", @@ -51,57 +49,14 @@ func TestConvertCloudSchedulerSource(t *testing.T) { "attribute2": "value2", }, }, - sendMode: Binary, - wantEventFn: func() *cloudevents.Event { - return schedulerCloudEvent(map[string]string{ - "attribute1": "value1", - "attribute2": "value2"}, - "//cloudscheduler.googleapis.com/projects/knative-gcp-test/locations/us-east4/schedulers/scheduler-test", - "jobs/cre-scheduler-test") - }, - }, { - name: "upper case attributes", - message: &cepubsub.Message{ - Data: []byte("test data"), - Attributes: map[string]string{ - "knative-gcp": "com.google.cloud.scheduler", - "jobName": "projects/knative-gcp-test/locations/us-east4/jobs/cre-scheduler-test", - "schedulerName": "scheduler-test", - "AttriBUte1": "value1", - "AttrIbuTe2": "value2", - }, - }, - sendMode: Binary, - wantEventFn: func() *cloudevents.Event { - return schedulerCloudEvent(map[string]string{ - "attribute1": "value1", - "attribute2": "value2", - }, - "//cloudscheduler.googleapis.com/projects/knative-gcp-test/locations/us-east4/schedulers/scheduler-test", - "jobs/cre-scheduler-test") - }, - }, { - name: "only setting valid alphanumeric attribute", - message: &cepubsub.Message{ - Data: []byte("test data"), - Attributes: map[string]string{ - "knative-gcp": "com.google.cloud.scheduler", - "jobName": "projects/knative-gcp-test/locations/us-east4/jobs/cre-scheduler-test", - "schedulerName": "scheduler-test", - "attribute1": "value1", - "Invalid-Attrib#$^": "value2", - }, - }, - sendMode: Binary, - wantEventFn: func() *cloudevents.Event { - return schedulerCloudEvent(map[string]string{ - "attribute1": "value1"}, + wantEventFn: func() *cev2.Event { + return schedulerCloudEvent( "//cloudscheduler.googleapis.com/projects/knative-gcp-test/locations/us-east4/schedulers/scheduler-test", "jobs/cre-scheduler-test") }, }, { name: "missing jobName attribute", - message: &cepubsub.Message{ + message: &pubsub.Message{ Data: []byte("test data"), Attributes: map[string]string{ "knative-gcp": "com.google.cloud.scheduler", @@ -110,11 +65,10 @@ func TestConvertCloudSchedulerSource(t *testing.T) { "attribute2": "value2", }, }, - sendMode: Binary, - wantErr: "received event did not have jobName", + wantErr: "received event did not have jobName", }, { name: "missing schedulerName attribute", - message: &cepubsub.Message{ + message: &pubsub.Message{ Data: []byte("test data"), Attributes: map[string]string{ "knative-gcp": "com.google.cloud.scheduler", @@ -123,23 +77,13 @@ func TestConvertCloudSchedulerSource(t *testing.T) { "attribute2": "value2", }, }, - sendMode: Binary, - wantErr: "received event did not have schedulerName", + wantErr: "received event did not have schedulerName", }} for _, test := range tests { t.Run(test.name, func(t *testing.T) { - ctx := pubsubcontext.WithTransportContext(context.Background(), pubsubcontext.NewTransportContext( - "testproject", - "testtopic", - "testsubscription", - "testmethod", - &pubsub.Message{ - ID: "id", - }, - )) - gotEvent, err := Convert(ctx, test.message, test.sendMode, "") + gotEvent, err := Convert(context.Background(), test.message, "") if test.wantErr != "" || err != nil { var gotErr string @@ -154,26 +98,18 @@ func TestConvertCloudSchedulerSource(t *testing.T) { } if diff := cmp.Diff(test.wantEventFn(), gotEvent); diff != "" { - t.Errorf("converters.convertCloudScheduler got unexpeceted cloudevents.Event (-want +got) %s", diff) + t.Errorf("converters.convertCloudScheduler got unexpected cev2.Event (-want +got) %s", diff) } }) } } -func schedulerCloudEvent(extensions map[string]string, source, subject string) *cloudevents.Event { - e := cloudevents.NewEvent(cloudevents.VersionV1) +func schedulerCloudEvent(source, subject string) *cev2.Event { + e := cev2.NewEvent(cev2.VersionV1) e.SetID("id") - e.SetDataContentType("application/octet-stream") - e.SetType(v1alpha1.CloudSchedulerSourceExecute) - e.SetExtension("knativecemode", string(Binary)) + e.SetData(cev2.ApplicationJSON, []byte("test data")) + e.SetType(v1beta1.CloudSchedulerSourceExecute) e.SetSource(source) e.SetSubject(subject) - e.Data = []byte("test data") - e.DataEncoded = true - for k, v := range extensions { - if k != v1alpha1.CloudSchedulerSourceJobName { - e.SetExtension(k, v) - } - } return &e } diff --git a/pkg/pubsub/adapter/converters/storage.go b/pkg/pubsub/adapter/converters/storage.go index 6c957ff024..a89041ed78 100644 --- a/pkg/pubsub/adapter/converters/storage.go +++ b/pkg/pubsub/adapter/converters/storage.go @@ -17,31 +17,25 @@ limitations under the License. package converters import ( + "cloud.google.com/go/pubsub" "context" "errors" - - "go.uber.org/zap" - "knative.dev/pkg/logging" - - cloudevents "github.com/cloudevents/sdk-go" - . "github.com/cloudevents/sdk-go/pkg/cloudevents" - cepubsub "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub" - pubsubcontext "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/context" - "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" + "fmt" + cev2 "github.com/cloudevents/sdk-go/v2" + "github.com/google/knative-gcp/pkg/apis/events/v1beta1" ) var ( // Mapping of GCS eventTypes to CloudEvent types. storageEventTypes = map[string]string{ - "OBJECT_FINALIZE": v1alpha1.CloudStorageSourceFinalize, - "OBJECT_ARCHIVE": v1alpha1.CloudStorageSourceArchive, - "OBJECT_DELETE": v1alpha1.CloudStorageSourceDelete, - "OBJECT_METADATA_UPDATE": v1alpha1.CloudStorageSourceMetadataUpdate, + "OBJECT_FINALIZE": v1beta1.CloudStorageSourceFinalize, + "OBJECT_ARCHIVE": v1beta1.CloudStorageSourceArchive, + "OBJECT_DELETE": v1beta1.CloudStorageSourceDelete, + "OBJECT_METADATA_UPDATE": v1beta1.CloudStorageSourceMetadataUpdate, } ) const ( - storageDefaultEventType = "com.google.cloud.storage" // Schema extracted from https://raw.githubusercontent.com/googleapis/google-api-go-client/master/storage/v1/storage-api.json. // TODO find the public google endpoint we should use to point to the schema and avoid hosting it ourselves. // The link above is tied to the go-client, and it seems not to be a valid json schema. @@ -49,59 +43,34 @@ const ( CloudStorageConverter = "com.google.cloud.storage" ) -func convertCloudStorage(ctx context.Context, msg *cepubsub.Message, sendMode ModeType) (*cloudevents.Event, error) { - if msg == nil { - return nil, errors.New("nil pubsub message") - } - - tx := pubsubcontext.TransportContextFrom(ctx) - // Make a new event and convert the message payload. - event := cloudevents.NewEvent(cloudevents.VersionV1) - event.SetID(tx.ID) - event.SetTime(tx.PublishTime) +func convertCloudStorage(ctx context.Context, msg *pubsub.Message) (*cev2.Event, error) { + event := cev2.NewEvent(cev2.VersionV1) + event.SetID(msg.ID) + event.SetTime(msg.PublishTime) event.SetDataSchema(storageSchemaUrl) if val, ok := msg.Attributes["bucketId"]; ok { - delete(msg.Attributes, "bucketId") - event.SetSource(v1alpha1.CloudStorageSourceEventSource(val)) + event.SetSource(v1beta1.CloudStorageSourceEventSource(val)) } else { return nil, errors.New("received event did not have bucketId") } if val, ok := msg.Attributes["objectId"]; ok { - delete(msg.Attributes, "objectId") event.SetSubject(val) } else { - // Not setting subject, as it's optional - logging.FromContext(ctx).Desugar().Debug("received event did not have objectId") + return nil, errors.New("received event did not have objectId") } if val, ok := msg.Attributes["eventType"]; ok { - delete(msg.Attributes, "eventType") if eventType, ok := storageEventTypes[val]; ok { event.SetType(eventType) } else { - logging.FromContext(ctx).Desugar().Debug("Unknown eventType, using default", zap.String("eventType", eventType), zap.String("default", storageDefaultEventType)) - event.SetType(storageDefaultEventType) + return nil, fmt.Errorf("unknown event type %s", val) } } else { return nil, errors.New("received event did not have eventType") } - if _, ok := msg.Attributes["eventTime"]; ok { - delete(msg.Attributes, "eventTime") - } - event.SetDataContentType(*cloudevents.StringOfApplicationJSON()) - event.Data = msg.Data - event.DataEncoded = true - // Attributes are extensions. - if msg.Attributes != nil && len(msg.Attributes) > 0 { - for k, v := range msg.Attributes { - // CloudEvents v1.0 attributes MUST consist of lower-case letters ('a' to 'z') or digits ('0' to '9') as per - // the spec. It's not even possible for a conformant transport to allow non-base36 characters. - // Note `SetExtension` will make it lowercase so only `IsAlphaNumeric` needs to be checked here. - if IsAlphaNumeric(k) { - event.SetExtension(k, v) - } - } + if err := event.SetData(cev2.ApplicationJSON, msg); err != nil { + return nil, err } return &event, nil } diff --git a/pkg/pubsub/adapter/converters/storage_test.go b/pkg/pubsub/adapter/converters/storage_test.go index 7e2f5bb076..39cacb2c1e 100644 --- a/pkg/pubsub/adapter/converters/storage_test.go +++ b/pkg/pubsub/adapter/converters/storage_test.go @@ -19,171 +19,159 @@ package converters import ( "context" "testing" + "time" "cloud.google.com/go/pubsub" - "github.com/google/go-cmp/cmp" + "github.com/google/knative-gcp/pkg/apis/events/v1beta1" - cloudevents "github.com/cloudevents/sdk-go" - cepubsub "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub" - pubsubcontext "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/context" - "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" + cev2 "github.com/cloudevents/sdk-go/v2" +) + +const ( + bucket = "my-bucket" + objectId = "myfile.jpg" + eventType = "OBJECT_FINALIZE" +) + +var ( + storagePublishTime = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) ) func TestConvertCloudStorageSource(t *testing.T) { tests := []struct { name string - message *cepubsub.Message - sendMode ModeType - wantEventFn func() *cloudevents.Event + message *pubsub.Message + wantEventFn func() *cev2.Event wantErr bool }{{ name: "no attributes", - message: &cepubsub.Message{ + message: &pubsub.Message{ Data: []byte("test data"), Attributes: map[string]string{ "knative-gcp": "com.google.cloud.storage", }, }, - sendMode: Binary, - wantEventFn: func() *cloudevents.Event { - return storageCloudEvent(map[string]string{}) + wantEventFn: func() *cev2.Event { + return storageCloudEvent() }, wantErr: true, }, { name: "no bucketId attribute", - message: &cepubsub.Message{ + message: &pubsub.Message{ Data: []byte("test data"), Attributes: map[string]string{ "knative-gcp": "com.google.cloud.storage", - "eventType": "OBJECT_FINALIZE", + "eventType": eventType, "attribute1": "value1", "attribute2": "value2", }, }, - sendMode: Binary, - wantEventFn: func() *cloudevents.Event { - return storageCloudEvent(map[string]string{ - "attribute1": "value1", - "attribute2": "value2", - }) + wantEventFn: func() *cev2.Event { + return storageCloudEvent() }, wantErr: true, }, { name: "no eventType attribute", - message: &cepubsub.Message{ + message: &pubsub.Message{ Data: []byte("test data"), Attributes: map[string]string{ "knative-gcp": "com.google.cloud.storage", - "bucketId": "my-bucket", + "bucketId": bucket, + "objectId": objectId, }, }, - sendMode: Binary, - wantEventFn: func() *cloudevents.Event { - return storageCloudEvent(map[string]string{}) + wantEventFn: func() *cev2.Event { + return storageCloudEvent() }, wantErr: true, }, { - name: "set subject", - message: &cepubsub.Message{ + name: "unkown eventType attribute", + message: &pubsub.Message{ Data: []byte("test data"), Attributes: map[string]string{ "knative-gcp": "com.google.cloud.storage", - "bucketId": "my-bucket", - "eventType": "OBJECT_FINALIZE", - "objectId": "myfile.jpg", - "AttriBUte1": "value1", - "AttrIbuTe2": "value2", + "eventType": "RANDOM_EVENT", + "bucketId": bucket, + "objectId": objectId, }, }, - sendMode: Binary, - wantEventFn: func() *cloudevents.Event { - return storageCloudEvent(map[string]string{ - "attribute1": "value1", - "attribute2": "value2", - }, - "myfile.jpg") + wantEventFn: func() *cev2.Event { + return storageCloudEvent() }, + wantErr: true, }, { - name: "not setting invalid upper case attributes", - message: &cepubsub.Message{ + name: "no objectId attribute", + message: &pubsub.Message{ Data: []byte("test data"), Attributes: map[string]string{ "knative-gcp": "com.google.cloud.storage", - "bucketId": "my-bucket", - "eventType": "OBJECT_FINALIZE", - "AttriBUte1": "value1", - "AttrIbuTe2": "value2", + "bucketId": bucket, + "eventType": eventType, }, }, - sendMode: Binary, - wantEventFn: func() *cloudevents.Event { - return storageCloudEvent(map[string]string{ - "attribute1": "value1", - "attribute2": "value2", - }) + wantEventFn: func() *cev2.Event { + return storageCloudEvent() }, + wantErr: true, }, { - name: "only setting valid alphanumeric attribute", - message: &cepubsub.Message{ + name: "valid message", + message: &pubsub.Message{ + ID: "id", + PublishTime: storagePublishTime, Data: []byte("test data"), Attributes: map[string]string{ - "knative-gcp": "com.google.cloud.storage", - "bucketId": "my-bucket", - "eventType": "OBJECT_FINALIZE", - "attribute1": "value1", - "Invalid-Attrib#$^": "value2", + "knative-gcp": "com.google.cloud.storage", + "bucketId": bucket, + "eventType": eventType, + "objectId": objectId, }, }, - sendMode: Binary, - wantEventFn: func() *cloudevents.Event { - return storageCloudEvent(map[string]string{ - "attribute1": "value1", - }) + wantEventFn: func() *cev2.Event { + return storageCloudEvent() }, }} for _, test := range tests { t.Run(test.name, func(t *testing.T) { - ctx := pubsubcontext.WithTransportContext(context.TODO(), pubsubcontext.NewTransportContext( - "testproject", - "testtopic", - "testsubscription", - "testmethod", - &pubsub.Message{ - ID: "id", - }, - )) - - gotEvent, err := Convert(ctx, test.message, test.sendMode, "") + gotEvent, err := Convert(context.Background(), test.message, "") if err != nil { if !test.wantErr { t.Fatalf("converters.convertCloudStorage got error %v want error=%v", err, test.wantErr) } } else { - if diff := cmp.Diff(test.wantEventFn(), gotEvent); diff != "" { - t.Fatalf("converters.convertCloudStorage got unexpeceted cloudevents.Event (-want +got) %s", diff) + if gotEvent.ID() != "id" { + t.Errorf("ID '%s' != '%s'", gotEvent.ID(), "id") + } + if !gotEvent.Time().Equal(storagePublishTime) { + t.Errorf("Time '%v' != '%v'", gotEvent.Time(), storagePublishTime) + } + if want := v1beta1.CloudStorageSourceEventSource("my-bucket"); gotEvent.Source() != want { + t.Errorf("Source %q != %q", gotEvent.Source(), want) + } + if gotEvent.Type() != v1beta1.CloudStorageSourceFinalize { + t.Errorf(`Type %q != %q`, gotEvent.Type(), v1beta1.CloudStorageSourceFinalize) + } + if gotEvent.Subject() != objectId { + t.Errorf("Subject %q != %q", gotEvent.Subject(), objectId) + } + if gotEvent.DataSchema() != storageSchemaUrl { + t.Errorf("DataSchema %q != %q", gotEvent.DataSchema(), storageSchemaUrl) } } }) } } -func storageCloudEvent(extensions map[string]string, subject ...string) *cloudevents.Event { - e := cloudevents.NewEvent(cloudevents.VersionV1) +func storageCloudEvent() *cev2.Event { + e := cev2.NewEvent(cev2.VersionV1) e.SetID("id") - e.SetDataContentType(*cloudevents.StringOfApplicationJSON()) + e.SetTime(storagePublishTime) + e.SetData(cev2.ApplicationJSON, []byte("test data")) e.SetDataSchema(storageSchemaUrl) - e.SetSource(v1alpha1.CloudStorageSourceEventSource("my-bucket")) - e.SetType(v1alpha1.CloudStorageSourceFinalize) - if len(subject) > 0 { - e.SetSubject(subject[0]) - } - e.Data = []byte("test data") - e.DataEncoded = true - for k, v := range extensions { - e.SetExtension(k, v) - } + e.SetSource(v1beta1.CloudStorageSourceEventSource(bucket)) + e.SetType(v1beta1.CloudStorageSourceFinalize) + e.SetSubject(objectId) return &e } diff --git a/pkg/pubsub/adapter/providers.go b/pkg/pubsub/adapter/providers.go new file mode 100644 index 0000000000..7f46f50f12 --- /dev/null +++ b/pkg/pubsub/adapter/providers.go @@ -0,0 +1,33 @@ +package adapter + +import ( + "context" + + "cloud.google.com/go/pubsub" + "github.com/google/knative-gcp/pkg/utils/clients" + "github.com/google/wire" +) + +// TODO Name and ResourceGroup might cause problems in the near future, as we might use a single receive-adapter +// for multiple source objects. Same with Namespace, when doing multi-tenancy. +type Name string +type Namespace string +type ResourceGroup string +type AdapterType string + +type SinkURI string +type TransformerURI string +type SubscriptionID string + +// AdapterSet provides an adapter with a PubSub client and HTTP client. +var AdapterSet wire.ProviderSet = wire.NewSet( + NewAdapter, + clients.NewPubsubClient, + NewPubSubSubscription, + NewStatsReporter, + clients.NewHTTPClient, +) + +func NewPubSubSubscription(ctx context.Context, client *pubsub.Client, subscriptionID SubscriptionID) *pubsub.Subscription { + return client.Subscription(string(subscriptionID)) +} diff --git a/pkg/pubsub/adapter/stats_reporter.go b/pkg/pubsub/adapter/stats_reporter.go index 0a98b313b7..bbe088c4ab 100644 --- a/pkg/pubsub/adapter/stats_reporter.go +++ b/pkg/pubsub/adapter/stats_reporter.go @@ -18,6 +18,7 @@ package adapter import ( "context" + "fmt" "strconv" "go.opencensus.io/stats/view" @@ -51,15 +52,8 @@ var ( ) type ReportArgs struct { - Namespace string - EventType string - EventSource string - Name string - ResourceGroup string -} - -func init() { - register() + EventType string + EventSource string } // StatsReporter defines the interface for sending metrics. @@ -72,11 +66,23 @@ var _ StatsReporter = (*reporter)(nil) var emptyContext = context.Background() // reporter holds cached metric objects to report metrics. -type reporter struct{} +type reporter struct { + name string + namespace string + resourceGroup string +} // NewStatsReporter creates a reporter that collects and reports metrics. -func NewStatsReporter() StatsReporter { - return &reporter{} +func NewStatsReporter(name Name, namespace Namespace, resourceGroup ResourceGroup) (StatsReporter, error) { + r := &reporter{ + name: string(name), + namespace: string(namespace), + resourceGroup: string(resourceGroup), + } + if err := r.register(); err != nil { + return nil, fmt.Errorf("failed to register stats: %w", err) + } + return r, nil } func (r *reporter) ReportEventCount(args *ReportArgs, responseCode int) error { @@ -91,16 +97,16 @@ func (r *reporter) ReportEventCount(args *ReportArgs, responseCode int) error { func (r *reporter) generateTag(args *ReportArgs, responseCode int) (context.Context, error) { return tag.New( emptyContext, - tag.Insert(namespaceKey, args.Namespace), + tag.Insert(namespaceKey, r.namespace), tag.Insert(eventSourceKey, args.EventSource), tag.Insert(eventTypeKey, args.EventType), - tag.Insert(nameKey, args.Name), - tag.Insert(resourceGroupKey, args.ResourceGroup), + tag.Insert(nameKey, r.name), + tag.Insert(resourceGroupKey, r.resourceGroup), tag.Insert(responseCodeKey, strconv.Itoa(responseCode)), tag.Insert(responseCodeClassKey, metrics.ResponseCodeClass(responseCode))) } -func register() { +func (r *reporter) register() error { tagKeys := []tag.Key{ namespaceKey, eventSourceKey, @@ -111,14 +117,12 @@ func register() { responseCodeClassKey} // Create view to see our measurements. - if err := view.Register( + return view.Register( &view.View{ Description: eventCountM.Description(), Measure: eventCountM, Aggregation: view.Count(), TagKeys: tagKeys, }, - ); err != nil { - panic(err) - } + ) } diff --git a/pkg/pubsub/adapter/stats_reporter_test.go b/pkg/pubsub/adapter/stats_reporter_test.go index 502b0ce3c1..97edb19424 100644 --- a/pkg/pubsub/adapter/stats_reporter_test.go +++ b/pkg/pubsub/adapter/stats_reporter_test.go @@ -27,17 +27,12 @@ import ( ) func TestStatsReporter(t *testing.T) { - setup() - args := &ReportArgs{ - Namespace: "testns", - EventType: "dev.knative.event", - EventSource: "unit-test", - Name: "testobject", - ResourceGroup: "testresourcegroup", + EventType: "dev.knative.event", + EventSource: "unit-test", } - r := NewStatsReporter() + r, _ := NewStatsReporter("testobject", "testns", "testresourcegroup") wantTags := map[string]string{ metricskey.LabelNamespaceName: "testns", @@ -65,13 +60,3 @@ func expectSuccess(t *testing.T, f func() error) { t.Errorf("Reporter expected success but got error: %v", err) } } - -func setup() { - resetMetrics() -} - -func resetMetrics() { - // OpenCensus metrics carry global state that need to be reset between unit tests. - metricstest.Unregister("event_count") - register() -} diff --git a/pkg/pubsub/publisher/providers.go b/pkg/pubsub/publisher/providers.go new file mode 100644 index 0000000000..ff65dd06a8 --- /dev/null +++ b/pkg/pubsub/publisher/providers.go @@ -0,0 +1,26 @@ +package publisher + +import ( + "context" + + "cloud.google.com/go/pubsub" + "github.com/google/knative-gcp/pkg/utils/clients" + "github.com/google/wire" + "knative.dev/eventing/pkg/kncloudevents" +) + +type TopicID string + +// PublisherSet provides a handler with a real HTTPMessageReceiver and a PubSub client. +var PublisherSet wire.ProviderSet = wire.NewSet( + NewPublisher, + clients.NewHTTPMessageReceiver, + clients.NewPubsubClient, + NewPubSubTopic, + wire.Bind(new(HttpMessageReceiver), new(*kncloudevents.HttpMessageReceiver)), +) + +// NewPubSubTopic provides a pubsub topic from a PubSub client. +func NewPubSubTopic(ctx context.Context, client *pubsub.Client, topicID TopicID) *pubsub.Topic { + return client.Topic(string(topicID)) +} diff --git a/pkg/pubsub/publisher/publisher.go b/pkg/pubsub/publisher/publisher.go index 20607a60b3..ecdf72924a 100644 --- a/pkg/pubsub/publisher/publisher.go +++ b/pkg/pubsub/publisher/publisher.go @@ -17,79 +17,129 @@ limitations under the License. package publisher import ( + "context" + "errors" "fmt" + nethttp "net/http" + "time" + "cloud.google.com/go/pubsub" + "github.com/cloudevents/sdk-go/v2/binding" + "github.com/cloudevents/sdk-go/v2/binding/transformer" + "github.com/cloudevents/sdk-go/v2/protocol/http" "go.uber.org/zap" - "knative.dev/pkg/logging" + "knative.dev/eventing/pkg/logging" - "context" + cev2 "github.com/cloudevents/sdk-go/v2" + "github.com/cloudevents/sdk-go/v2/protocol" + + cepubsub "github.com/cloudevents/sdk-go/protocol/pubsub/v2" + "github.com/cloudevents/sdk-go/v2/extensions" + "go.opencensus.io/trace" +) - cloudevents "github.com/cloudevents/sdk-go" - cepubsub "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub" - "knative.dev/eventing/pkg/kncloudevents" +const ( + sinkTimeout = 30 * time.Second ) -// Publisher implements the Pub/Sub adapter to deliver Pub/Sub messages from a -// pre-existing topic/subscription to a Sink. +// PubSubPublisher is an interface to publish events to a pubsub topic. +type PubSubPublisher interface { + Publish(ctx context.Context, event cev2.Event) protocol.Result +} + +// HttpMessageReceiver is an interface to listen on http requests. +type HttpMessageReceiver interface { + StartListen(ctx context.Context, handler nethttp.Handler) error +} + +// Publisher receives HTTP events and sends them to Pubsub. type Publisher struct { - // ProjectID is the pre-existing eventing project id to use. - ProjectID string - // TopicID is the pre-existing eventing pub/sub topic id to use. - TopicID string - - // inbound is the cloudevents client to use to receive events. - inbound cloudevents.Client - // outbound is the cloudevents client to use to send events. - outbound cloudevents.Client + // inbound is an HTTP server to receive events. + inbound HttpMessageReceiver + // topic is the topic to publish events to. + topic *pubsub.Topic + + logger *zap.Logger } -func (a *Publisher) Start(ctx context.Context) error { - var err error +// NewPublisher creates a new publisher. +func NewPublisher(ctx context.Context, inbound HttpMessageReceiver, topic *pubsub.Topic) *Publisher { + return &Publisher{ + inbound: inbound, + topic: topic, + logger: logging.FromContext(ctx), + } +} - // Receive events on HTTP. - if a.inbound == nil { - if a.inbound, err = kncloudevents.NewDefaultClient(); err != nil { - return fmt.Errorf("failed to create inbound cloudevent client: %w", err) - } +// Start blocks to receive events over HTTP. +func (p *Publisher) Start(ctx context.Context) error { + return p.inbound.StartListen(ctx, p) +} + +// ServeHTTP implements net/http Publisher interface method. +// 1. Performs basic validation of the request. +// 2. Converts the request to an event. +// 3. Sends the event to pubsub. +func (p *Publisher) ServeHTTP(response nethttp.ResponseWriter, request *nethttp.Request) { + ctx := request.Context() + p.logger.Debug("Serving http", zap.Any("headers", request.Header)) + if request.Method != nethttp.MethodPost { + response.WriteHeader(nethttp.StatusMethodNotAllowed) + return } - // Send Events on Pub/Sub. - if a.outbound == nil { - if a.outbound, err = a.newPubSubClient(ctx); err != nil { - return fmt.Errorf("failed to create outbound cloudevent client: %w", err) - } + event, err := p.toEvent(request) + if err != nil { + nethttp.Error(response, err.Error(), nethttp.StatusBadRequest) + return } - return a.inbound.StartReceiver(ctx, a.receive) + // Optimistically set status code to StatusAccepted. It will be updated if there is an error. + // According to the data plane spec (https://github.com/knative/eventing/blob/master/docs/spec/data-plane.md), a + // non-callable Sink (which Publisher is) MUST respond with 202 Accepted if the request is accepted. + statusCode := nethttp.StatusAccepted + ctx, cancel := context.WithTimeout(ctx, sinkTimeout) + defer cancel() + if res := p.Publish(ctx, *event); !cev2.IsACK(res) { + msg := fmt.Sprintf("Error publishing to PubSub. event: %+v, err: %v.", event, res) + p.logger.Error(msg) + statusCode = nethttp.StatusInternalServerError + nethttp.Error(response, msg, statusCode) + return + } + response.WriteHeader(statusCode) } -func (a *Publisher) receive(ctx context.Context, event cloudevents.Event, resp *cloudevents.EventResponse) error { - if _, r, err := a.outbound.Send(ctx, event); err != nil { - logging.FromContext(ctx).Desugar().Error("Error publishing to PubSub", zap.String("event", event.String()), zap.Error(err)) +// Publish publishes an incoming event to a pubsub topic. +func (p *Publisher) Publish(ctx context.Context, event cev2.Event) protocol.Result { + dt := extensions.FromSpanContext(trace.FromContext(ctx).SpanContext()) + msg := new(pubsub.Message) + if err := cepubsub.WritePubSubMessage(ctx, binding.ToMessage(&event), msg, dt.WriteTransformer()); err != nil { return err - } else if r != nil { - resp.RespondWith(200, r) } - - return nil + _, err := p.topic.Publish(ctx, msg).Get(ctx) + return err } -func (a *Publisher) newPubSubClient(ctx context.Context) (cloudevents.Client, error) { - tOpts := []cepubsub.Option{ - cepubsub.WithBinaryEncoding(), - cepubsub.WithProjectID(a.ProjectID), - cepubsub.WithTopicID(a.TopicID), +// toEvent converts an http request to an event. +func (p *Publisher) toEvent(request *nethttp.Request) (*cev2.Event, error) { + message := http.NewMessageFromHttpRequest(request) + defer func() { + if err := message.Finish(nil); err != nil { + p.logger.Error("Failed to close message", zap.Any("message", message), zap.Error(err)) + } + }() + // If encoding is unknown, the message is not an event. + if message.ReadEncoding() == binding.EncodingUnknown { + msg := fmt.Sprintf("Encoding is unknown. Not a cloud event? request: %+v", request) + p.logger.Debug(msg) + return nil, errors.New(msg) } - - // Make a pubsub transport for the CloudEvents client. - t, err := cepubsub.New(ctx, tOpts...) + event, err := binding.ToEvent(request.Context(), message, transformer.AddTimeNow) if err != nil { - return nil, err + msg := fmt.Sprintf("Failed to convert request to event: %v", err) + p.logger.Error(msg) + return nil, errors.New(msg) } - - // Use the transport to make a new CloudEvents client. - return cloudevents.NewClient(t, - cloudevents.WithUUIDs(), - cloudevents.WithTimeNow(), - ) + return event, nil } diff --git a/pkg/broker/ingress/args.go b/pkg/utils/clients/factories.go similarity index 67% rename from pkg/broker/ingress/args.go rename to pkg/utils/clients/factories.go index f0ea2ef75a..6e72afec98 100644 --- a/pkg/broker/ingress/args.go +++ b/pkg/utils/clients/factories.go @@ -14,10 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package ingress +package clients import ( "context" + nethttp "net/http" + "time" + + "go.opencensus.io/plugin/ochttp" + "go.opencensus.io/plugin/ochttp/propagation/tracecontext" "cloud.google.com/go/pubsub" cepubsub "github.com/cloudevents/sdk-go/protocol/pubsub/v2" @@ -27,6 +32,7 @@ import ( type Port int type ProjectID string +type MaxConnsPerHost int // NewHTTPMessageReceiver wraps kncloudevents.NewHttpMessageReceiver with type-safe options. func NewHTTPMessageReceiver(port Port) *kncloudevents.HttpMessageReceiver { @@ -38,9 +44,8 @@ func NewPubsubClient(ctx context.Context, projectID ProjectID) (*pubsub.Client, return pubsub.NewClient(ctx, string(projectID)) } -// NewPubsubDecoupleClient creates a pubsub Cloudevents client to use to publish events to decouple queues. -func NewPubsubDecoupleClient(ctx context.Context, client *pubsub.Client) (cev2.Client, error) { - // Make a pubsub protocol for the CloudEvents client. +// NewObservedPubsubClient creates a pubsub Cloudevents client with observability support. +func NewObservedPubsubClient(ctx context.Context, client *pubsub.Client) (cev2.Client, error) { p, err := cepubsub.New(ctx, cepubsub.WithClient(client)) if err != nil { return nil, err @@ -53,3 +58,17 @@ func NewPubsubDecoupleClient(ctx context.Context, client *pubsub.Client) (cev2.C cev2.WithTracePropagation, ) } + +func NewHTTPClient(ctx context.Context, maxConnsPerHost MaxConnsPerHost) *nethttp.Client { + return &nethttp.Client{ + Transport: &ochttp.Transport{ + Base: &nethttp.Transport{ + MaxIdleConns: 1000, + MaxIdleConnsPerHost: int(maxConnsPerHost), + MaxConnsPerHost: int(maxConnsPerHost), + IdleConnTimeout: 30 * time.Second, + }, + Propagation: &tracecontext.HTTPFormat{}, + }, + } +} From 55aa08be3dd1e537f9413dc6c3f6e2165c51dae6 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Wed, 17 Jun 2020 08:43:43 -0700 Subject: [PATCH 02/28] updating wire gen and moving push to pubsub converter --- cmd/pubsub/publisher/wire_gen.go | 2 +- pkg/pubsub/adapter/converters/pubsub.go | 29 +++++++++++++++++++++++ pkg/pubsub/adapter/converters/push.go | 31 ------------------------- 3 files changed, 30 insertions(+), 32 deletions(-) delete mode 100644 pkg/pubsub/adapter/converters/push.go diff --git a/cmd/pubsub/publisher/wire_gen.go b/cmd/pubsub/publisher/wire_gen.go index 674f21ada8..8110e6af06 100644 --- a/cmd/pubsub/publisher/wire_gen.go +++ b/cmd/pubsub/publisher/wire_gen.go @@ -20,6 +20,6 @@ func InitializePublisher(ctx context.Context, port clients.Port, projectID clien return nil, err } topic := publisher.NewPubSubTopic(ctx, client, topicID) - publisherPublisher := publisher.NewPublisher(ctx, httpMessageReceiver, client, topic) + publisherPublisher := publisher.NewPublisher(ctx, httpMessageReceiver, topic) return publisherPublisher, nil } diff --git a/pkg/pubsub/adapter/converters/pubsub.go b/pkg/pubsub/adapter/converters/pubsub.go index 8d020619b1..bb48003807 100644 --- a/pkg/pubsub/adapter/converters/pubsub.go +++ b/pkg/pubsub/adapter/converters/pubsub.go @@ -18,6 +18,7 @@ package converters import ( "context" + "time" "cloud.google.com/go/pubsub" cev2 "github.com/cloudevents/sdk-go/v2" @@ -62,3 +63,31 @@ func convertPubSub(ctx context.Context, msg *pubsub.Message) (*cev2.Event, error } return &event, nil } + +// PushMessage represents the format Pub/Sub uses to push events. +type PushMessage struct { + // Subscription is the subscription ID that received this Message. + Subscription string `json:"subscription"` + // Message holds the Pub/Sub message contents. + Message *PubSubMessage `json:"message,omitempty"` +} + +// PubSubMessage matches the inner message format used by Push Subscriptions. +type PubSubMessage struct { + // ID identifies this message. This ID is assigned by the server and is + // populated for Messages obtained from a subscription. + // This field is read-only. + ID string `json:"messageId,omitempty"` + + // Data is the actual data in the message. + Data interface{} `json:"data,omitempty"` + + // Attributes represents the key-value pairs the current message + // is labelled with. + Attributes map[string]string `json:"attributes,omitempty"` + + // The time at which the message was published. This is populated by the + // server for Messages obtained from a subscription. + // This field is read-only. + PublishTime time.Time `json:"publishTime,omitempty"` +} diff --git a/pkg/pubsub/adapter/converters/push.go b/pkg/pubsub/adapter/converters/push.go deleted file mode 100644 index 46e553f8ff..0000000000 --- a/pkg/pubsub/adapter/converters/push.go +++ /dev/null @@ -1,31 +0,0 @@ -package converters - -import "time" - -// PushMessage represents the format Pub/Sub uses to push events. -type PushMessage struct { - // Subscription is the subscription ID that received this Message. - Subscription string `json:"subscription"` - // Message holds the Pub/Sub message contents. - Message *PubSubMessage `json:"message,omitempty"` -} - -// PubSubMessage matches the inner message format used by Push Subscriptions. -type PubSubMessage struct { - // ID identifies this message. This ID is assigned by the server and is - // populated for Messages obtained from a subscription. - // This field is read-only. - ID string `json:"messageId,omitempty"` - - // Data is the actual data in the message. - Data interface{} `json:"data,omitempty"` - - // Attributes represents the key-value pairs the current message - // is labelled with. - Attributes map[string]string `json:"attributes,omitempty"` - - // The time at which the message was published. This is populated by the - // server for Messages obtained from a subscription. - // This field is read-only. - PublishTime time.Time `json:"publishTime,omitempty"` -} From ab6cb04395cffc5a2f9f8f4e6c4b0ede913e5675 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Wed, 17 Jun 2020 09:16:16 -0700 Subject: [PATCH 03/28] update-codegen --- .../pkg/cloudevents/transport/pubsub/codec.go | 116 ------- .../transport/pubsub/codec_structured.go | 40 --- .../cloudevents/transport/pubsub/codec_v03.go | 286 ---------------- .../cloudevents/transport/pubsub/codec_v1.go | 242 ------------- .../transport/pubsub/context/context.go | 94 ------ .../pkg/cloudevents/transport/pubsub/doc.go | 4 - .../cloudevents/transport/pubsub/encoding.go | 114 ------- .../transport/pubsub/internal/connection.go | 210 ------------ .../cloudevents/transport/pubsub/message.go | 47 --- .../cloudevents/transport/pubsub/options.go | 207 ------------ .../cloudevents/transport/pubsub/transport.go | 317 ------------------ vendor/modules.txt | 3 - 12 files changed, 1680 deletions(-) delete mode 100644 vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec.go delete mode 100644 vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec_structured.go delete mode 100644 vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec_v03.go delete mode 100644 vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec_v1.go delete mode 100644 vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/context/context.go delete mode 100644 vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/doc.go delete mode 100644 vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/encoding.go delete mode 100644 vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/internal/connection.go delete mode 100644 vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/message.go delete mode 100644 vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/options.go delete mode 100644 vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/transport.go diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec.go deleted file mode 100644 index 4401ef75b5..0000000000 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec.go +++ /dev/null @@ -1,116 +0,0 @@ -package pubsub - -import ( - "context" - "errors" - "fmt" - "sync" - - "github.com/cloudevents/sdk-go/pkg/cloudevents" - cecontext "github.com/cloudevents/sdk-go/pkg/cloudevents/context" - "github.com/cloudevents/sdk-go/pkg/cloudevents/transport" -) - -type Codec struct { - Encoding Encoding - - // DefaultEncodingSelectionFn allows for encoding selection strategies to be injected. - DefaultEncodingSelectionFn EncodingSelector - - v03 *CodecV03 - v1 *CodecV1 - - _v03 sync.Once - _v1 sync.Once -} - -const ( - prefix = "ce-" -) - -var _ transport.Codec = (*Codec)(nil) - -func (c *Codec) loadCodec(encoding Encoding) (transport.Codec, error) { - switch encoding { - case Default: - fallthrough - case BinaryV1, StructuredV1: - c._v1.Do(func() { - c.v1 = &CodecV1{DefaultEncoding: c.Encoding} - }) - return c.v1, nil - case BinaryV03, StructuredV03: - c._v03.Do(func() { - c.v03 = &CodecV03{DefaultEncoding: c.Encoding} - }) - return c.v03, nil - } - - return nil, fmt.Errorf("unknown encoding: %s", encoding) -} - -func (c *Codec) Encode(ctx context.Context, e cloudevents.Event) (transport.Message, error) { - encoding := c.Encoding - if encoding == Default && c.DefaultEncodingSelectionFn != nil { - encoding = c.DefaultEncodingSelectionFn(ctx, e) - } - codec, err := c.loadCodec(encoding) - if err != nil { - return nil, err - } - ctx = cecontext.WithEncoding(ctx, encoding.Name()) - return codec.Encode(ctx, e) -} - -func (c *Codec) Decode(ctx context.Context, msg transport.Message) (*cloudevents.Event, error) { - codec, err := c.loadCodec(c.inspectEncoding(ctx, msg)) - if err != nil { - return nil, err - } - event, err := codec.Decode(ctx, msg) - if err != nil { - return nil, err - } - return c.convertEvent(event) -} - -// Give the context back as the user expects -func (c *Codec) convertEvent(event *cloudevents.Event) (*cloudevents.Event, error) { - if event == nil { - return nil, errors.New("event is nil, can not convert") - } - - switch c.Encoding { - case Default: - return event, nil - case BinaryV03, StructuredV03: - ca := event.Context.AsV03() - event.Context = ca - return event, nil - case BinaryV1, StructuredV1: - ca := event.Context.AsV1() - event.Context = ca - return event, nil - default: - return nil, fmt.Errorf("unknown encoding: %s", c.Encoding) - } -} - -func (c *Codec) inspectEncoding(ctx context.Context, msg transport.Message) Encoding { - // Try v1.0. - _, _ = c.loadCodec(BinaryV1) - encoding := c.v1.inspectEncoding(ctx, msg) - if encoding != Unknown { - return encoding - } - - // Try v0.3. - _, _ = c.loadCodec(BinaryV03) - encoding = c.v03.inspectEncoding(ctx, msg) - if encoding != Unknown { - return encoding - } - - // We do not understand the message encoding. - return Unknown -} diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec_structured.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec_structured.go deleted file mode 100644 index 9ecafe604d..0000000000 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec_structured.go +++ /dev/null @@ -1,40 +0,0 @@ -package pubsub - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/cloudevents/sdk-go/pkg/cloudevents" - "github.com/cloudevents/sdk-go/pkg/cloudevents/transport" -) - -// CodecStructured represents an structured http transport codec for all versions. -// Intended to be used as a base class. -type CodecStructured struct { - Encoding Encoding -} - -func (v CodecStructured) encodeStructured(ctx context.Context, e cloudevents.Event) (transport.Message, error) { - data, err := json.Marshal(e) - if err != nil { - return nil, err - } - - msg := &Message{ - Attributes: map[string]string{StructuredContentType: cloudevents.ApplicationCloudEventsJSON}, - Data: data, - } - - return msg, nil -} - -func (v CodecStructured) decodeStructured(ctx context.Context, version string, msg transport.Message) (*cloudevents.Event, error) { - m, ok := msg.(*Message) - if !ok { - return nil, fmt.Errorf("failed to convert transport.Message to pubsub.Message") - } - event := cloudevents.New(version) - err := json.Unmarshal(m.Data, &event) - return &event, err -} diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec_v03.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec_v03.go deleted file mode 100644 index d96ab3a699..0000000000 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec_v03.go +++ /dev/null @@ -1,286 +0,0 @@ -package pubsub - -import ( - "context" - "encoding/json" - "fmt" - "strings" - - "github.com/cloudevents/sdk-go/pkg/cloudevents" - cecontext "github.com/cloudevents/sdk-go/pkg/cloudevents/context" - "github.com/cloudevents/sdk-go/pkg/cloudevents/transport" - "github.com/cloudevents/sdk-go/pkg/cloudevents/types" -) - -const ( - StructuredContentType = "Content-Type" -) - -type CodecV03 struct { - CodecStructured - - DefaultEncoding Encoding -} - -var _ transport.Codec = (*CodecV03)(nil) - -func (v CodecV03) Encode(ctx context.Context, e cloudevents.Event) (transport.Message, error) { - encoding := v.DefaultEncoding - strEnc := cecontext.EncodingFrom(ctx) - if strEnc != "" { - switch strEnc { - case Binary: - encoding = BinaryV03 - case Structured: - encoding = StructuredV03 - } - } - switch encoding { - case Default: - fallthrough - case StructuredV03: - return v.encodeStructured(ctx, e) - case BinaryV03: - return v.encodeBinary(ctx, e) - default: - return nil, fmt.Errorf("unknown encoding: %d", encoding) - } -} - -func (v CodecV03) Decode(ctx context.Context, msg transport.Message) (*cloudevents.Event, error) { - // only structured is supported as of v0.3 - switch v.inspectEncoding(ctx, msg) { - case StructuredV03: - return v.decodeStructured(ctx, cloudevents.CloudEventsVersionV03, msg) - case BinaryV03: - event := cloudevents.New(cloudevents.CloudEventsVersionV03) - return v.decodeBinary(ctx, msg, &event) - default: - return nil, transport.NewErrMessageEncodingUnknown("v03", TransportName) - } -} - -func (v CodecV03) inspectEncoding(ctx context.Context, msg transport.Message) Encoding { - version := msg.CloudEventsVersion() - if version != cloudevents.CloudEventsVersionV03 { - return Unknown - } - m, ok := msg.(*Message) - if !ok { - return Unknown - } - if m.Attributes[StructuredContentType] == cloudevents.ApplicationCloudEventsJSON { - return StructuredV03 - } - return BinaryV03 -} - -func (v CodecV03) encodeBinary(ctx context.Context, e cloudevents.Event) (transport.Message, error) { - attributes, err := v.toAttributes(e) - if err != nil { - return nil, err - } - data, err := e.DataBytes() - if err != nil { - return nil, err - } - - msg := &Message{ - Attributes: attributes, - Data: data, - } - - return msg, nil -} - -func (v CodecV03) toAttributes(e cloudevents.Event) (map[string]string, error) { - a := make(map[string]string) - a[prefix+"specversion"] = e.SpecVersion() - a[prefix+"type"] = e.Type() - a[prefix+"source"] = e.Source() - a[prefix+"id"] = e.ID() - if !e.Time().IsZero() { - t := types.Timestamp{Time: e.Time()} // TODO: change e.Time() to return string so I don't have to do this. - a[prefix+"time"] = t.String() - } - if e.DataSchema() != "" { - a[prefix+"schemaurl"] = e.DataSchema() - } - - if e.DataContentType() != "" { - a[prefix+"datacontenttype"] = e.DataContentType() - } else { - a[prefix+"datacontenttype"] = cloudevents.ApplicationJSON - } - - if e.Subject() != "" { - a[prefix+"subject"] = e.Subject() - } - - if e.DeprecatedDataContentEncoding() != "" { - a[prefix+"datacontentencoding"] = e.DeprecatedDataContentEncoding() - } - - for k, v := range e.Extensions() { - if mapVal, ok := v.(map[string]interface{}); ok { - for subkey, subval := range mapVal { - encoded, err := json.Marshal(subval) - if err != nil { - return nil, err - } - a[prefix+k+"-"+subkey] = string(encoded) - } - continue - } - if s, ok := v.(string); ok { - a[prefix+k] = s - continue - } - encoded, err := json.Marshal(v) - if err != nil { - return nil, err - } - a[prefix+k] = string(encoded) - } - - return a, nil -} - -func (v CodecV03) decodeBinary(ctx context.Context, msg transport.Message, event *cloudevents.Event) (*cloudevents.Event, error) { - m, ok := msg.(*Message) - if !ok { - return nil, fmt.Errorf("failed to convert transport.Message to pubsub.Message") - } - err := v.fromAttributes(m.Attributes, event) - if err != nil { - return nil, err - } - var data interface{} - if len(m.Data) > 0 { - data = m.Data - } - event.Data = data - event.DataEncoded = true - return event, nil -} - -func (v CodecV03) fromAttributes(a map[string]string, event *cloudevents.Event) error { - // Normalize attributes. - for k, v := range a { - ck := strings.ToLower(k) - if k != ck { - delete(a, k) - a[ck] = v - } - } - - ec := event.Context - - if sv := a[prefix+"specversion"]; sv != "" { - if err := ec.SetSpecVersion(sv); err != nil { - return err - } - } - delete(a, prefix+"specversion") - - if id := a[prefix+"id"]; id != "" { - if err := ec.SetID(id); err != nil { - return err - } - } - delete(a, prefix+"id") - - if t := a[prefix+"type"]; t != "" { - if err := ec.SetType(t); err != nil { - return err - } - } - delete(a, prefix+"type") - - if s := a[prefix+"source"]; s != "" { - if err := ec.SetSource(s); err != nil { - return err - } - } - delete(a, prefix+"source") - - if t := a[prefix+"time"]; t != "" { - if timestamp, err := types.ParseTimestamp(t); err != nil { - return err - } else if err := ec.SetTime(timestamp.Time); err != nil { - return err - } - } - delete(a, prefix+"time") - - if s := a[prefix+"schemaurl"]; s != "" { - if err := ec.SetDataSchema(s); err != nil { - return err - } - } - delete(a, prefix+"schemaurl") - - if s := a[prefix+"subject"]; s != "" { - if err := ec.SetSubject(s); err != nil { - return err - } - } - delete(a, prefix+"subject") - - if s := a[prefix+"datacontenttype"]; s != "" { - if err := ec.SetDataContentType(s); err != nil { - return err - } - } - delete(a, prefix+"datacontenttype") - - if s := a[prefix+"datacontentencoding"]; s != "" { - if err := ec.DeprecatedSetDataContentEncoding(s); err != nil { - return err - } - } - delete(a, prefix+"datacontentencoding") - - // At this point, we have deleted all the known headers. - // Everything left is assumed to be an extension. - - extensions := make(map[string]interface{}) - for k, v := range a { - if len(k) > len(prefix) && strings.EqualFold(k[:len(prefix)], prefix) { - ak := strings.ToLower(k[len(prefix):]) - if i := strings.Index(ak, "-"); i > 0 { - // attrib-key - attrib := ak[:i] - key := ak[(i + 1):] - if xv, ok := extensions[attrib]; ok { - if m, ok := xv.(map[string]interface{}); ok { - m[key] = v - continue - } - // TODO: revisit how we want to bubble errors up. - return fmt.Errorf("failed to process map type extension") - } else { - m := make(map[string]interface{}) - m[key] = v - extensions[attrib] = m - } - } else { - // key - var tmp interface{} - if err := json.Unmarshal([]byte(v), &tmp); err == nil { - extensions[ak] = tmp - } else { - // If we can't unmarshal the data, treat it as a string. - extensions[ak] = v - } - } - } - } - event.Context = ec - if len(extensions) > 0 { - for k, v := range extensions { - event.SetExtension(k, v) - } - } - return nil -} diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec_v1.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec_v1.go deleted file mode 100644 index 2d091010a7..0000000000 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/codec_v1.go +++ /dev/null @@ -1,242 +0,0 @@ -package pubsub - -import ( - "context" - "fmt" - "strings" - - "github.com/cloudevents/sdk-go/pkg/cloudevents" - cecontext "github.com/cloudevents/sdk-go/pkg/cloudevents/context" - "github.com/cloudevents/sdk-go/pkg/cloudevents/transport" - "github.com/cloudevents/sdk-go/pkg/cloudevents/types" -) - -type CodecV1 struct { - CodecStructured - - DefaultEncoding Encoding -} - -var _ transport.Codec = (*CodecV1)(nil) - -func (v CodecV1) Encode(ctx context.Context, e cloudevents.Event) (transport.Message, error) { - encoding := v.DefaultEncoding - strEnc := cecontext.EncodingFrom(ctx) - if strEnc != "" { - switch strEnc { - case Binary: - encoding = BinaryV1 - case Structured: - encoding = StructuredV1 - } - } - switch encoding { - case Default: - fallthrough - case StructuredV1: - return v.encodeStructured(ctx, e) - case BinaryV1: - return v.encodeBinary(ctx, e) - default: - return nil, fmt.Errorf("unknown encoding: %d", v.Encoding) - } -} - -func (v CodecV1) Decode(ctx context.Context, msg transport.Message) (*cloudevents.Event, error) { - // only structured is supported as of v0.3 - switch v.inspectEncoding(ctx, msg) { - case StructuredV1: - return v.decodeStructured(ctx, cloudevents.CloudEventsVersionV1, msg) - case BinaryV1: - event := cloudevents.New(cloudevents.CloudEventsVersionV1) - return v.decodeBinary(ctx, msg, &event) - default: - return nil, transport.NewErrMessageEncodingUnknown("V1", TransportName) - } -} - -func (v CodecV1) inspectEncoding(ctx context.Context, msg transport.Message) Encoding { - version := msg.CloudEventsVersion() - if version != cloudevents.CloudEventsVersionV1 { - return Unknown - } - m, ok := msg.(*Message) - if !ok { - return Unknown - } - if m.Attributes[StructuredContentType] == cloudevents.ApplicationCloudEventsJSON { - return StructuredV1 - } - return BinaryV1 -} - -func (v CodecV1) encodeBinary(ctx context.Context, e cloudevents.Event) (transport.Message, error) { - attributes, err := v.toAttributes(e) - if err != nil { - return nil, err - } - data, err := e.DataBytes() - if err != nil { - return nil, err - } - - msg := &Message{ - Attributes: attributes, - Data: data, - } - - return msg, nil -} - -func (v CodecV1) toAttributes(e cloudevents.Event) (map[string]string, error) { - a := make(map[string]string) - a[prefix+"specversion"] = e.SpecVersion() - a[prefix+"type"] = e.Type() - a[prefix+"source"] = e.Source() - a[prefix+"id"] = e.ID() - if !e.Time().IsZero() { - t := types.Timestamp{Time: e.Time()} // TODO: change e.Time() to return string so I don't have to do this. - a[prefix+"time"] = t.String() - } - if e.DataSchema() != "" { - a[prefix+"dataschema"] = e.DataSchema() - } - - if e.DataContentType() != "" { - a[prefix+"datacontenttype"] = e.DataContentType() - } else { - a[prefix+"datacontenttype"] = cloudevents.ApplicationJSON - } - - if e.Subject() != "" { - a[prefix+"subject"] = e.Subject() - } - - if e.DeprecatedDataContentEncoding() != "" { - a[prefix+"datacontentencoding"] = e.DeprecatedDataContentEncoding() - } - - for k, v := range e.Extensions() { - k = strings.ToLower(k) - cstr, err := types.Format(v) - if err != nil { - return a, err - } - a[prefix+k] = cstr - } - return a, nil -} - -func (v CodecV1) decodeBinary(ctx context.Context, msg transport.Message, event *cloudevents.Event) (*cloudevents.Event, error) { - m, ok := msg.(*Message) - if !ok { - return nil, fmt.Errorf("failed to convert transport.Message to pubsub.Message") - } - err := v.fromAttributes(m.Attributes, event) - if err != nil { - return nil, err - } - var data interface{} - if len(m.Data) > 0 { - data = m.Data - } - event.Data = data - event.DataEncoded = true - return event, nil -} - -func (v CodecV1) fromAttributes(a map[string]string, event *cloudevents.Event) error { - // Normalize attributes. - for k, v := range a { - ck := strings.ToLower(k) - if k != ck { - delete(a, k) - a[ck] = v - } - } - - ec := event.Context - - if sv := a[prefix+"specversion"]; sv != "" { - if err := ec.SetSpecVersion(sv); err != nil { - return err - } - } - delete(a, prefix+"specversion") - - if id := a[prefix+"id"]; id != "" { - if err := ec.SetID(id); err != nil { - return err - } - } - delete(a, prefix+"id") - - if t := a[prefix+"type"]; t != "" { - if err := ec.SetType(t); err != nil { - return err - } - } - delete(a, prefix+"type") - - if s := a[prefix+"source"]; s != "" { - if err := ec.SetSource(s); err != nil { - return err - } - } - delete(a, prefix+"source") - - if t := a[prefix+"time"]; t != "" { - if timestamp, err := types.ParseTimestamp(t); err != nil { - return err - } else if err := ec.SetTime(timestamp.Time); err != nil { - return err - } - } - delete(a, prefix+"time") - - if s := a[prefix+"dataschema"]; s != "" { - if err := ec.SetDataSchema(s); err != nil { - return err - } - } - delete(a, prefix+"dataschema") - - if s := a[prefix+"subject"]; s != "" { - if err := ec.SetSubject(s); err != nil { - return err - } - } - delete(a, prefix+"subject") - - if s := a[prefix+"datacontenttype"]; s != "" { - if err := ec.SetDataContentType(s); err != nil { - return err - } - } - delete(a, prefix+"datacontenttype") - - if s := a[prefix+"datacontentencoding"]; s != "" { - if err := ec.DeprecatedSetDataContentEncoding(s); err != nil { - return err - } - } - delete(a, prefix+"datacontentencoding") - - // At this point, we have deleted all the known headers. - // Everything left is assumed to be an extension. - - extensions := make(map[string]interface{}) - for k, v := range a { - if len(k) > len(prefix) && strings.EqualFold(k[:len(prefix)], prefix) { - ak := strings.ToLower(k[len(prefix):]) - extensions[ak] = v - } - } - event.Context = ec - if len(extensions) > 0 { - for k, v := range extensions { - event.SetExtension(k, v) - } - } - return nil -} diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/context/context.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/context/context.go deleted file mode 100644 index e64a5ee71b..0000000000 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/context/context.go +++ /dev/null @@ -1,94 +0,0 @@ -package context - -import ( - "context" - "strings" - "time" - - "cloud.google.com/go/pubsub" -) - -// TransportContext allows a Receiver to understand the context of a request. -type TransportContext struct { - ID string - PublishTime time.Time - Project string - Topic string - Subscription string - Method string // push or pull -} - -// NewTransportContext creates a new TransportContext from a pubsub.Message. -func NewTransportContext(project, topic, subscription, method string, msg *pubsub.Message) TransportContext { - var tx *TransportContext - if msg != nil { - tx = &TransportContext{ - ID: msg.ID, - PublishTime: msg.PublishTime, - Project: project, - Topic: topic, - Subscription: subscription, - Method: method, - } - } else { - tx = &TransportContext{} - } - return *tx -} - -// String generates a pretty-printed version of the resource as a string. -func (tx TransportContext) String() string { - b := strings.Builder{} - - b.WriteString("Transport Context,\n") - - if tx.ID != "" { - b.WriteString(" ID: " + tx.ID + "\n") - } - if !tx.PublishTime.IsZero() { - b.WriteString(" PublishTime: " + tx.PublishTime.String() + "\n") - } - - if tx.Project != "" { - b.WriteString(" Project: " + tx.Project + "\n") - } - - if tx.Topic != "" { - b.WriteString(" Topic: " + tx.Topic + "\n") - } - - if tx.Subscription != "" { - b.WriteString(" Subscription: " + tx.Subscription + "\n") - } - - if tx.Method != "" { - b.WriteString(" Method: " + tx.Method + "\n") - } - - return b.String() -} - -// Opaque key type used to store TransportContext -type transportContextKeyType struct{} - -var transportContextKey = transportContextKeyType{} - -// WithTransportContext return a context with the given TransportContext into the provided context object. -func WithTransportContext(ctx context.Context, tcxt TransportContext) context.Context { - return context.WithValue(ctx, transportContextKey, tcxt) -} - -// TransportContextFrom pulls a TransportContext out of a context. Always -// returns a non-nil object. -func TransportContextFrom(ctx context.Context) TransportContext { - tctx := ctx.Value(transportContextKey) - if tctx != nil { - if tx, ok := tctx.(TransportContext); ok { - return tx - } - if tx, ok := tctx.(*TransportContext); ok { - return *tx - } - } - return TransportContext{} -} diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/doc.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/doc.go deleted file mode 100644 index b45504609c..0000000000 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -/* -Package pubsub implements the CloudEvent transport implementation using pubsub. -*/ -package pubsub diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/encoding.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/encoding.go deleted file mode 100644 index 33717f720b..0000000000 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/encoding.go +++ /dev/null @@ -1,114 +0,0 @@ -package pubsub - -import ( - "context" - - "github.com/cloudevents/sdk-go/pkg/cloudevents" -) - -// Encoding to use for pubsub transport. -type Encoding int32 - -type EncodingSelector func(context.Context, cloudevents.Event) Encoding - -const ( - // Default allows pubsub transport implementation to pick. - Default Encoding = iota - // BinaryV03 is Binary CloudEvents spec v0.3. - BinaryV03 - // BinaryV1 is Binary CloudEvents spec v1.0. - BinaryV1 - // StructuredV03 is Structured CloudEvents spec v0.3. - StructuredV03 - // StructuredV1 is Structured CloudEvents spec v1.0. - StructuredV1 - - // Unknown is unknown. - Unknown - - // Binary is used for Context Based Encoding Selections to use the - // DefaultBinaryEncodingSelectionStrategy - Binary = "binary" - - // Structured is used for Context Based Encoding Selections to use the - // DefaultStructuredEncodingSelectionStrategy - Structured = "structured" -) - -// DefaultBinaryEncodingSelectionStrategy implements a selection process for -// which binary encoding to use based on spec version of the event. -func DefaultBinaryEncodingSelectionStrategy(ctx context.Context, e cloudevents.Event) Encoding { - switch e.SpecVersion() { - case cloudevents.CloudEventsVersionV01, cloudevents.CloudEventsVersionV02, cloudevents.CloudEventsVersionV03: - return BinaryV03 - case cloudevents.CloudEventsVersionV1: - return BinaryV1 - } - // Unknown version, return Default. - return Default -} - -// DefaultStructuredEncodingSelectionStrategy implements a selection process -// for which structured encoding to use based on spec version of the event. -func DefaultStructuredEncodingSelectionStrategy(ctx context.Context, e cloudevents.Event) Encoding { - switch e.SpecVersion() { - case cloudevents.CloudEventsVersionV01, cloudevents.CloudEventsVersionV02, cloudevents.CloudEventsVersionV03: - return StructuredV03 - case cloudevents.CloudEventsVersionV1: - return StructuredV1 - } - // Unknown version, return Default. - return Default -} - -// String pretty-prints the encoding as a string. -func (e Encoding) String() string { - switch e { - case Default: - return "Default Encoding " + e.Version() - - // Binary - case BinaryV03, BinaryV1: - return "Binary Encoding " + e.Version() - - // Structured - case StructuredV03, StructuredV1: - return "Structured Encoding " + e.Version() - - default: - return "Unknown Encoding" - } -} - -// Version pretty-prints the encoding version as a string. -func (e Encoding) Version() string { - switch e { - - // Version 0.2 - // Version 0.3 - case Default, BinaryV03, StructuredV03: - return "v0.3" - - // Version 1.0 - case BinaryV1, StructuredV1: - return "v1.0" - - // Unknown - default: - return "Unknown" - } -} - -// Name creates a string to represent the the codec name. -func (e Encoding) Name() string { - switch e { - case Default: - return Binary - case BinaryV03, BinaryV1: - return Binary - case StructuredV03, StructuredV1: - return Structured - default: - return Binary - } -} diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/internal/connection.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/internal/connection.go deleted file mode 100644 index 8265651618..0000000000 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/internal/connection.go +++ /dev/null @@ -1,210 +0,0 @@ -package internal - -import ( - "context" - "errors" - "fmt" - "sync" - "time" - - "cloud.google.com/go/pubsub" - "github.com/cloudevents/sdk-go/pkg/cloudevents" - pscontext "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/context" -) - -// Connection acts as either a pubsub topic or a pubsub subscription . -type Connection struct { - // AllowCreateTopic controls if the transport can create a topic if it does - // not exist. - AllowCreateTopic bool - - // AllowCreateSubscription controls if the transport can create a - // subscription if it does not exist. - AllowCreateSubscription bool - - ProjectID string - - Client *pubsub.Client - - TopicID string - topic *pubsub.Topic - topicWasCreated bool - topicOnce sync.Once - - SubscriptionID string - sub *pubsub.Subscription - subWasCreated bool - subOnce sync.Once - - // ReceiveSettings is used to configure Pubsub pull subscription. - ReceiveSettings *pubsub.ReceiveSettings - - // AckDeadline is Pub/Sub AckDeadline. - // Default is 30 seconds. - AckDeadline *time.Duration - // RetentionDuration is Pub/Sub RetentionDuration. - // Default is 25 hours. - RetentionDuration *time.Duration -} - -const ( - DefaultAckDeadline = 30 * time.Second - DefaultRetentionDuration = 25 * time.Hour -) - -var DefaultReceiveSettings = pubsub.ReceiveSettings{ - // Pubsub default receive settings will fill in other values. - // https://godoc.org/cloud.google.com/go/pubsub#Client.Subscription - - // Override the default number of goroutines. - // This is a magical number now. This has shown throughput improvements empirically - // by at least 10x (compared to the default value). - NumGoroutines: 1000, - Synchronous: false, -} - -func (c *Connection) getOrCreateTopic(ctx context.Context) (*pubsub.Topic, error) { - var err error - c.topicOnce.Do(func() { - var ok bool - // Load the topic. - topic := c.Client.Topic(c.TopicID) - ok, err = topic.Exists(ctx) - if err != nil { - return - } - // If the topic does not exist, create a new topic with the given name. - if !ok { - if !c.AllowCreateTopic { - err = fmt.Errorf("transport not allowed to create topic %q", c.TopicID) - return - } - topic, err = c.Client.CreateTopic(ctx, c.TopicID) - if err != nil { - return - } - c.topicWasCreated = true - } - // Success. - c.topic = topic - }) - if c.topic == nil { - return nil, fmt.Errorf("unable to create topic %q, %v", c.TopicID, err) - } - return c.topic, err -} - -// DeleteTopic -func (c *Connection) DeleteTopic(ctx context.Context) error { - if !c.topicWasCreated { - return errors.New("topic was not created by pubsub transport") - } - if err := c.topic.Delete(ctx); err != nil { - return err - } - c.topic = nil - c.topicWasCreated = false - c.topicOnce = sync.Once{} - return nil -} - -func (c *Connection) getOrCreateSubscription(ctx context.Context) (*pubsub.Subscription, error) { - var err error - c.subOnce.Do(func() { - // Load the subscription. - var ok bool - sub := c.Client.Subscription(c.SubscriptionID) - ok, err = sub.Exists(ctx) - if err != nil { - return - } - // If subscription doesn't exist, create it. - if !ok { - if !c.AllowCreateSubscription { - err = fmt.Errorf("transport not allowed to create subscription %q", c.SubscriptionID) - return - } - - // Load the topic. - var topic *pubsub.Topic - topic, err = c.getOrCreateTopic(ctx) - if err != nil { - return - } - // Default the ack deadline and retention duration config. - if c.AckDeadline == nil { - ackDeadline := DefaultAckDeadline - c.AckDeadline = &(ackDeadline) - } - if c.RetentionDuration == nil { - retentionDuration := DefaultRetentionDuration - c.RetentionDuration = &retentionDuration - } - - // Create a new subscription to the previously created topic - // with the given name. - // TODO: allow to use push config + allow setting the SubscriptionConfig. - sub, err = c.Client.CreateSubscription(ctx, c.SubscriptionID, pubsub.SubscriptionConfig{ - Topic: topic, - AckDeadline: *c.AckDeadline, - RetentionDuration: *c.RetentionDuration, - }) - if err != nil { - _ = c.Client.Close() - return - } - if c.ReceiveSettings == nil { - sub.ReceiveSettings = DefaultReceiveSettings - } else { - sub.ReceiveSettings = *c.ReceiveSettings - } - c.subWasCreated = true - } - // Success. - c.sub = sub - }) - if c.sub == nil { - return nil, fmt.Errorf("unable to create sunscription %q, %v", c.SubscriptionID, err) - } - return c.sub, err -} - -// DeleteSubscription -func (c *Connection) DeleteSubscription(ctx context.Context) error { - if !c.subWasCreated { - return errors.New("subscription was not created by pubsub transport") - } - if err := c.sub.Delete(ctx); err != nil { - return err - } - c.sub = nil - c.subWasCreated = false - c.subOnce = sync.Once{} - return nil -} - -// Publish -func (c *Connection) Publish(ctx context.Context, msg *pubsub.Message) (*cloudevents.Event, error) { - topic, err := c.getOrCreateTopic(ctx) - if err != nil { - return nil, err - } - - r := topic.Publish(ctx, msg) - _, err = r.Get(ctx) - return nil, err -} - -// Start -// NOTE: This is a blocking call. -func (c *Connection) Receive(ctx context.Context, fn func(context.Context, *pubsub.Message)) error { - sub, err := c.getOrCreateSubscription(ctx) - if err != nil { - return err - } - // Ok, ready to start pulling. - return sub.Receive(ctx, func(ctx context.Context, m *pubsub.Message) { - ctx = pscontext.WithTransportContext(ctx, pscontext.NewTransportContext(c.ProjectID, c.TopicID, c.SubscriptionID, "pull", m)) - fn(ctx, m) - }) -} diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/message.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/message.go deleted file mode 100644 index 3430e581b4..0000000000 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/message.go +++ /dev/null @@ -1,47 +0,0 @@ -package pubsub - -import ( - "encoding/json" - - "github.com/cloudevents/sdk-go/pkg/cloudevents/transport" -) - -// type check that this transport message impl matches the contract -var _ transport.Message = (*Message)(nil) - -// Message represents a Pub/Sub message. -type Message struct { - // Data is the actual data in the message. - Data []byte - - // Attributes represents the key-value pairs the current message - // is labelled with. - Attributes map[string]string -} - -func (m Message) CloudEventsVersion() string { - // Check as Binary encoding first. - if m.Attributes != nil { - // Binary v0.3: - if s := m.Attributes[prefix+"specversion"]; s != "" { - return s - } - } - - // Now check as Structured encoding. - raw := make(map[string]json.RawMessage) - if err := json.Unmarshal(m.Data, &raw); err != nil { - return "" - } - - // structured v0.3 - if v, ok := raw["specversion"]; ok { - var version string - if err := json.Unmarshal(v, &version); err != nil { - return "" - } - return version - } - - return "" -} diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/options.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/options.go deleted file mode 100644 index a77adb246a..0000000000 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/options.go +++ /dev/null @@ -1,207 +0,0 @@ -package pubsub - -import ( - "fmt" - "os" - - "cloud.google.com/go/pubsub" -) - -// Option is the function signature required to be considered an pubsub.Option. -type Option func(*Transport) error - -const ( - DefaultProjectEnvKey = "GOOGLE_CLOUD_PROJECT" - DefaultTopicEnvKey = "PUBSUB_TOPIC" - DefaultSubscriptionEnvKey = "PUBSUB_SUBSCRIPTION" -) - -// WithEncoding sets the encoding for pubsub transport. -func WithEncoding(encoding Encoding) Option { - return func(t *Transport) error { - t.Encoding = encoding - return nil - } -} - -// WithDefaultEncodingSelector sets the encoding selection strategy for -// default encoding selections based on Event. -func WithDefaultEncodingSelector(fn EncodingSelector) Option { - return func(t *Transport) error { - if t == nil { - return fmt.Errorf("http default encoding selector option can not set nil transport") - } - if fn != nil { - t.DefaultEncodingSelectionFn = fn - return nil - } - return fmt.Errorf("pubsub fn for DefaultEncodingSelector was nil") - } -} - -// WithBinaryEncoding sets the encoding selection strategy for -// default encoding selections based on Event, the encoded event will be the -// given version in Binary form. -func WithBinaryEncoding() Option { - return func(t *Transport) error { - if t == nil { - return fmt.Errorf("pubsub binary encoding option can not set nil transport") - } - - t.DefaultEncodingSelectionFn = DefaultBinaryEncodingSelectionStrategy - return nil - } -} - -// WithStructuredEncoding sets the encoding selection strategy for -// default encoding selections based on Event, the encoded event will be the -// given version in Structured form. -func WithStructuredEncoding() Option { - return func(t *Transport) error { - if t == nil { - return fmt.Errorf("pubsub structured encoding option can not set nil transport") - } - - t.DefaultEncodingSelectionFn = DefaultStructuredEncodingSelectionStrategy - return nil - } -} - -// WithClient sets the pubsub client for pubsub transport. Use this for explicit -// auth setup. Otherwise the env var 'GOOGLE_APPLICATION_CREDENTIALS' is used. -// See https://cloud.google.com/docs/authentication/production for more details. -func WithClient(client *pubsub.Client) Option { - return func(t *Transport) error { - t.client = client - return nil - } -} - -// WithProjectID sets the project ID for pubsub transport. -func WithProjectID(projectID string) Option { - return func(t *Transport) error { - t.projectID = projectID - return nil - } -} - -// WithProjectIDFromEnv sets the project ID for pubsub transport from a -// given environment variable name. -func WithProjectIDFromEnv(key string) Option { - return func(t *Transport) error { - v := os.Getenv(key) - if v == "" { - return fmt.Errorf("unable to load project id, %q environment variable not set", key) - } - t.projectID = v - return nil - } -} - -// WithProjectIDFromDefaultEnv sets the project ID for pubsub transport from -// the environment variable named 'GOOGLE_CLOUD_PROJECT'. -func WithProjectIDFromDefaultEnv() Option { - return WithProjectIDFromEnv(DefaultProjectEnvKey) -} - -// WithTopicID sets the topic ID for pubsub transport. -func WithTopicID(topicID string) Option { - return func(t *Transport) error { - t.topicID = topicID - return nil - } -} - -// WithTopicIDFromEnv sets the topic ID for pubsub transport from a given -// environment variable name. -func WithTopicIDFromEnv(key string) Option { - return func(t *Transport) error { - v := os.Getenv(key) - if v == "" { - return fmt.Errorf("unable to load topic id, %q environment variable not set", key) - } - t.topicID = v - return nil - } -} - -// WithTopicIDFromDefaultEnv sets the topic ID for pubsub transport from the -// environment variable named 'PUBSUB_TOPIC'. -func WithTopicIDFromDefaultEnv() Option { - return WithTopicIDFromEnv(DefaultTopicEnvKey) -} - -// WithSubscriptionID sets the subscription ID for pubsub transport. -// This option can be used multiple times. -func WithSubscriptionID(subscriptionID string) Option { - return func(t *Transport) error { - if t.subscriptions == nil { - t.subscriptions = make([]subscriptionWithTopic, 0) - } - t.subscriptions = append(t.subscriptions, subscriptionWithTopic{ - subscriptionID: subscriptionID, - }) - return nil - } -} - -// WithSubscriptionAndTopicID sets the subscription and topic IDs for pubsub transport. -// This option can be used multiple times. -func WithSubscriptionAndTopicID(subscriptionID, topicID string) Option { - return func(t *Transport) error { - if t.subscriptions == nil { - t.subscriptions = make([]subscriptionWithTopic, 0) - } - t.subscriptions = append(t.subscriptions, subscriptionWithTopic{ - subscriptionID: subscriptionID, - topicID: topicID, - }) - return nil - } -} - -// WithSubscriptionIDFromEnv sets the subscription ID for pubsub transport from -// a given environment variable name. -func WithSubscriptionIDFromEnv(key string) Option { - return func(t *Transport) error { - v := os.Getenv(key) - if v == "" { - return fmt.Errorf("unable to load subscription id, %q environment variable not set", key) - } - - opt := WithSubscriptionID(v) - return opt(t) - } -} - -// WithSubscriptionIDFromDefaultEnv sets the subscription ID for pubsub -// transport from the environment variable named 'PUBSUB_SUBSCRIPTION'. -func WithSubscriptionIDFromDefaultEnv() Option { - return WithSubscriptionIDFromEnv(DefaultSubscriptionEnvKey) -} - -// AllowCreateTopic sets if the transport can create a topic if it does not -// exist. -func AllowCreateTopic(allow bool) Option { - return func(t *Transport) error { - t.AllowCreateTopic = allow - return nil - } -} - -// AllowCreateSubscription sets if the transport can create a subscription if -// it does not exist. -func AllowCreateSubscription(allow bool) Option { - return func(t *Transport) error { - t.AllowCreateSubscription = allow - return nil - } -} - -// WithReceiveSettings sets the Pubsub ReceiveSettings for pull subscriptions. -func WithReceiveSettings(rs *pubsub.ReceiveSettings) Option { - return func(t *Transport) error { - t.ReceiveSettings = rs - return nil - } -} diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/transport.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/transport.go deleted file mode 100644 index 310d0d253f..0000000000 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/transport.go +++ /dev/null @@ -1,317 +0,0 @@ -package pubsub - -import ( - "context" - "errors" - "fmt" - "strings" - "sync" - - "go.uber.org/zap" - - "cloud.google.com/go/pubsub" - - "github.com/cloudevents/sdk-go/pkg/cloudevents" - cecontext "github.com/cloudevents/sdk-go/pkg/cloudevents/context" - "github.com/cloudevents/sdk-go/pkg/cloudevents/transport" - "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/internal" -) - -// Transport adheres to transport.Transport. -var _ transport.Transport = (*Transport)(nil) - -const ( - TransportName = "Pub/Sub" -) - -type subscriptionWithTopic struct { - topicID string - subscriptionID string -} - -// Transport acts as both a pubsub topic and a pubsub subscription . -type Transport struct { - // Encoding - Encoding Encoding - - // DefaultEncodingSelectionFn allows for other encoding selection strategies to be injected. - DefaultEncodingSelectionFn EncodingSelector - - codec transport.Codec - // Codec Mutex - coMu sync.Mutex - - // PubSub - - // ReceiveSettings is used to configure Pubsub pull subscription. - ReceiveSettings *pubsub.ReceiveSettings - - // AllowCreateTopic controls if the transport can create a topic if it does - // not exist. - AllowCreateTopic bool - - // AllowCreateSubscription controls if the transport can create a - // subscription if it does not exist. - AllowCreateSubscription bool - - projectID string - topicID string - subscriptionID string - - gccMux sync.Mutex - - subscriptions []subscriptionWithTopic - client *pubsub.Client - - connectionsBySubscription map[string]*internal.Connection - connectionsByTopic map[string]*internal.Connection - - // Receiver - Receiver transport.Receiver - - // Converter is invoked if the incoming transport receives an undecodable - // message. - Converter transport.Converter -} - -// New creates a new pubsub transport. -func New(ctx context.Context, opts ...Option) (*Transport, error) { - t := &Transport{} - if err := t.applyOptions(opts...); err != nil { - return nil, err - } - - if t.client == nil { - // Auth to pubsub. - client, err := pubsub.NewClient(ctx, t.projectID) - if err != nil { - return nil, err - } - // Success. - t.client = client - } - - if t.connectionsBySubscription == nil { - t.connectionsBySubscription = make(map[string]*internal.Connection, 0) - } - - if t.connectionsByTopic == nil { - t.connectionsByTopic = make(map[string]*internal.Connection, 0) - } - return t, nil -} - -func (t *Transport) applyOptions(opts ...Option) error { - for _, fn := range opts { - if err := fn(t); err != nil { - return err - } - } - return nil -} - -func (t *Transport) loadCodec(ctx context.Context) bool { - if t.codec == nil { - t.coMu.Lock() - if t.DefaultEncodingSelectionFn != nil && t.Encoding != Default { - logger := cecontext.LoggerFrom(ctx) - logger.Warn("transport has a DefaultEncodingSelectionFn set but Encoding is not Default. DefaultEncodingSelectionFn will be ignored.") - - t.codec = &Codec{ - Encoding: t.Encoding, - } - } else { - t.codec = &Codec{ - Encoding: t.Encoding, - DefaultEncodingSelectionFn: t.DefaultEncodingSelectionFn, - } - } - t.coMu.Unlock() - } - return true -} - -func (t *Transport) getConnection(ctx context.Context, topic, subscription string) *internal.Connection { - if subscription != "" { - if conn, ok := t.connectionsBySubscription[subscription]; ok { - return conn - } - } - if topic != "" { - if conn, ok := t.connectionsByTopic[topic]; ok { - return conn - } - } - - return nil -} - -func (t *Transport) getOrCreateConnection(ctx context.Context, topic, subscription string) *internal.Connection { - t.gccMux.Lock() - defer t.gccMux.Unlock() - - // Get. - if conn := t.getConnection(ctx, topic, subscription); conn != nil { - return conn - } - // Create. - conn := &internal.Connection{ - AllowCreateSubscription: t.AllowCreateSubscription, - AllowCreateTopic: t.AllowCreateTopic, - ReceiveSettings: t.ReceiveSettings, - Client: t.client, - ProjectID: t.projectID, - TopicID: topic, - SubscriptionID: subscription, - } - // Save for later. - if subscription != "" { - t.connectionsBySubscription[subscription] = conn - } - if topic != "" { - t.connectionsByTopic[topic] = conn - } - - return conn -} - -// Send implements Transport.Send -func (t *Transport) Send(ctx context.Context, event cloudevents.Event) (context.Context, *cloudevents.Event, error) { - // TODO populate response context properly. - if ok := t.loadCodec(ctx); !ok { - return ctx, nil, fmt.Errorf("unknown encoding set on transport: %d", t.Encoding) - } - - topic := cecontext.TopicFrom(ctx) - if topic == "" { - topic = t.topicID - } - - conn := t.getOrCreateConnection(ctx, topic, "") - - msg, err := t.codec.Encode(ctx, event) - if err != nil { - return ctx, nil, err - } - - if m, ok := msg.(*Message); ok { - respEvent, err := conn.Publish(ctx, &pubsub.Message{ - Attributes: m.Attributes, - Data: m.Data, - }) - return ctx, respEvent, err - } - - return ctx, nil, fmt.Errorf("failed to encode Event into a Message") -} - -// SetReceiver implements Transport.SetReceiver -func (t *Transport) SetReceiver(r transport.Receiver) { - t.Receiver = r -} - -// SetConverter implements Transport.SetConverter -func (t *Transport) SetConverter(c transport.Converter) { - t.Converter = c -} - -// HasConverter implements Transport.HasConverter -func (t *Transport) HasConverter() bool { - return t.Converter != nil -} - -func (t *Transport) startSubscriber(ctx context.Context, sub subscriptionWithTopic, done func(error)) { - logger := cecontext.LoggerFrom(ctx) - logger.Infof("starting subscriber for Topic %q, Subscription %q", sub.topicID, sub.subscriptionID) - conn := t.getOrCreateConnection(ctx, sub.topicID, sub.subscriptionID) - - logger.Info("conn is", conn) - if conn == nil { - err := fmt.Errorf("failed to find connection for Topic: %q, Subscription: %q", sub.topicID, sub.subscriptionID) - done(err) - return - } - // Ok, ready to start pulling. - err := conn.Receive(ctx, func(ctx context.Context, m *pubsub.Message) { - msg := &Message{ - Attributes: m.Attributes, - Data: m.Data, - } - event, err := t.codec.Decode(ctx, msg) - // If codec returns and error, try with the converter if it is set. - if err != nil && t.HasConverter() { - event, err = t.Converter.Convert(ctx, msg, err) - } - if err != nil { - logger.Errorw("failed to decode message", zap.Error(err)) - m.Nack() - return - } - - if err := t.Receiver.Receive(ctx, *event, nil); err != nil { - logger.Warnw("pubsub receiver return err", zap.Error(err)) - m.Nack() - return - } - m.Ack() - }) - done(err) -} - -// StartReceiver implements Transport.StartReceiver -// NOTE: This is a blocking call. -func (t *Transport) StartReceiver(ctx context.Context) error { - // Load the codec. - if ok := t.loadCodec(ctx); !ok { - return fmt.Errorf("unknown encoding set on transport: %d", t.Encoding) - } - - cctx, cancel := context.WithCancel(ctx) - defer cancel() - n := len(t.subscriptions) - - // Make the channels for quit and errors. - quit := make(chan struct{}, n) - errc := make(chan error, n) - - // Start up each subscription. - for _, sub := range t.subscriptions { - go t.startSubscriber(cctx, sub, func(err error) { - if err != nil { - errc <- err - } else { - quit <- struct{}{} - } - }) - } - - // Collect errors and done calls until we have n of them. - errs := []string(nil) - for success := 0; success < n; success++ { - var err error - select { - case <-ctx.Done(): // Block for parent context to finish. - success-- - case err = <-errc: // Collect errors - case <-quit: - } - if cancel != nil { - // Stop all other subscriptions. - cancel() - cancel = nil - } - if err != nil { - errs = append(errs, err.Error()) - } - } - - close(quit) - close(errc) - - return errors.New(strings.Join(errs, "\n")) -} - -// HasTracePropagation implements Transport.HasTracePropagation -func (t *Transport) HasTracePropagation() bool { - return false -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 9879828617..53434e3dc5 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -108,9 +108,6 @@ github.com/cloudevents/sdk-go/pkg/cloudevents/extensions github.com/cloudevents/sdk-go/pkg/cloudevents/observability github.com/cloudevents/sdk-go/pkg/cloudevents/transport github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http -github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub -github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/context -github.com/cloudevents/sdk-go/pkg/cloudevents/transport/pubsub/internal github.com/cloudevents/sdk-go/pkg/cloudevents/types # github.com/cloudevents/sdk-go/protocol/pubsub/v2 v2.0.1-0.20200602143929-d07dc0510d45 ## explicit From 33bae7f0a407d6fad06368a26a9c8053e162e08e Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Wed, 17 Jun 2020 12:10:11 -0700 Subject: [PATCH 04/28] injecting converter for better UTs --- cmd/pubsub/receive_adapter/wire_gen.go | 4 +- pkg/pubsub/adapter/adapter.go | 7 +++- .../adapter/converters/auditlogs_test.go | 4 +- pkg/pubsub/adapter/converters/build_test.go | 2 +- pkg/pubsub/adapter/converters/converters.go | 40 +++++++++++-------- pkg/pubsub/adapter/converters/pubsub_test.go | 2 +- .../adapter/converters/scheduler_test.go | 2 +- pkg/pubsub/adapter/converters/storage_test.go | 2 +- pkg/pubsub/adapter/providers.go | 2 + 9 files changed, 41 insertions(+), 24 deletions(-) diff --git a/cmd/pubsub/receive_adapter/wire_gen.go b/cmd/pubsub/receive_adapter/wire_gen.go index cb85eccb43..6cafa424d7 100644 --- a/cmd/pubsub/receive_adapter/wire_gen.go +++ b/cmd/pubsub/receive_adapter/wire_gen.go @@ -8,6 +8,7 @@ package main import ( "context" "github.com/google/knative-gcp/pkg/pubsub/adapter" + "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "github.com/google/knative-gcp/pkg/utils/clients" ) @@ -20,10 +21,11 @@ func InitializeAdapter(ctx context.Context, projectID clients.ProjectID, subscri } pubsubSubscription := adapter.NewPubSubSubscription(ctx, client, subscription) httpClient := clients.NewHTTPClient(ctx, maxConnsPerHost) + converter := converters.NewPubSubConverter() statsReporter, err := adapter.NewStatsReporter(name, namespace, resourceGroup) if err != nil { return nil, err } - adapterAdapter := adapter.NewAdapter(ctx, pubsubSubscription, httpClient, statsReporter, sinkURI, transformerURI, adapterType, extensions) + adapterAdapter := adapter.NewAdapter(ctx, pubsubSubscription, httpClient, converter, statsReporter, sinkURI, transformerURI, adapterType, extensions) return adapterAdapter, nil } diff --git a/pkg/pubsub/adapter/adapter.go b/pkg/pubsub/adapter/adapter.go index 60092c4e34..eab1ecd32f 100644 --- a/pkg/pubsub/adapter/adapter.go +++ b/pkg/pubsub/adapter/adapter.go @@ -57,6 +57,9 @@ type Adapter struct { // reporter reports metrics to the configured backend. reporter StatsReporter + // converter used to convert pubsub messages to CE. + converter converters.Converter + logger *zap.Logger } @@ -65,6 +68,7 @@ func NewAdapter( ctx context.Context, subscription *pubsub.Subscription, outbound *nethttp.Client, + converter converters.Converter, reporter StatsReporter, sinkURI SinkURI, transformerURI TransformerURI, @@ -73,6 +77,7 @@ func NewAdapter( return &Adapter{ subscription: subscription, outbound: outbound, + converter: converter, reporter: reporter, sinkURI: string(sinkURI), transformerURI: string(transformerURI), @@ -111,7 +116,7 @@ func (a *Adapter) Start(ctx context.Context) error { } func (a *Adapter) receive(ctx context.Context, msg *pubsub.Message) { - event, err := converters.Convert(ctx, msg, a.adapterType) + event, err := a.converter.Convert(ctx, msg, a.adapterType) if err != nil { a.logger.Debug("Failed to convert received message to an event, check the msg format: %w", zap.Error(err)) // Ack the message so it won't be retried diff --git a/pkg/pubsub/adapter/converters/auditlogs_test.go b/pkg/pubsub/adapter/converters/auditlogs_test.go index ffbb08fbe3..e4069079f9 100644 --- a/pkg/pubsub/adapter/converters/auditlogs_test.go +++ b/pkg/pubsub/adapter/converters/auditlogs_test.go @@ -76,7 +76,7 @@ func TestConvertAuditLog(t *testing.T) { Data: buf.Bytes(), } - e, err := Convert(context.Background(), &msg, CloudAuditLogsConverter) + e, err := NewPubSubConverter().Convert(context.Background(), &msg, CloudAuditLogsConverter) if err != nil { t.Fatalf("conversion failed: %v", err) @@ -144,7 +144,7 @@ func TestConvertTextPayload(t *testing.T) { Data: buf.Bytes(), } - _, err = Convert(context.Background(), &msg, CloudAuditLogsConverter) + _, err = NewPubSubConverter().Convert(context.Background(), &msg, CloudAuditLogsConverter) if err == nil { t.Errorf("Expected error when converting non-AuditLog LogEntry.") diff --git a/pkg/pubsub/adapter/converters/build_test.go b/pkg/pubsub/adapter/converters/build_test.go index ae91c37b6d..6e8ebb970e 100644 --- a/pkg/pubsub/adapter/converters/build_test.go +++ b/pkg/pubsub/adapter/converters/build_test.go @@ -95,7 +95,7 @@ func TestConvertCloudBuild(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { ctx := WithProjectKey(context.Background(), "testproject") - gotEvent, err := Convert(ctx, test.message, CloudBuildConverter) + gotEvent, err := NewPubSubConverter().Convert(ctx, test.message, CloudBuildConverter) if err != nil { if !test.wantErr { t.Errorf("converters.convertBuild got error %v want error=%v", err, test.wantErr) diff --git a/pkg/pubsub/adapter/converters/converters.go b/pkg/pubsub/adapter/converters/converters.go index 37e0681a03..cd23be6bf7 100644 --- a/pkg/pubsub/adapter/converters/converters.go +++ b/pkg/pubsub/adapter/converters/converters.go @@ -44,33 +44,41 @@ const ( type converterFn func(context.Context, *pubsub.Message) (*cev2.Event, error) -// converters is the map for handling Source specific event -// conversions. For example, a GCS event will need to be -// converted differently from the PubSub. The key into -// this map will be "knative-gcp" CloudEvent attribute. -// If there's no such attribute, we assume it's a native -// PubSub message and a default one will be used. -var converters map[string]converterFn +type Converter interface { + Convert(ctx context.Context, msg *pubsub.Message, converterType string) (*cev2.Event, error) +} + +type PubSubConverter struct { + // converters is the map for handling Source specific event + // conversions. For example, a GCS event will need to be + // converted differently from the PubSub. The key into + // this map will be "knative-gcp" CloudEvent attribute. + // If there's no such attribute, we assume it's a native + // PubSub message and a default one will be used. + converters map[string]converterFn +} -func init() { - converters = map[string]converterFn{ - CloudAuditLogsConverter: convertCloudAuditLogs, - CloudStorageConverter: convertCloudStorage, - CloudSchedulerConverter: convertCloudScheduler, - CloudBuildConverter: convertCloudBuild, +func NewPubSubConverter() Converter { + return &PubSubConverter{ + converters: map[string]converterFn{ + CloudAuditLogsConverter: convertCloudAuditLogs, + CloudStorageConverter: convertCloudStorage, + CloudSchedulerConverter: convertCloudScheduler, + CloudBuildConverter: convertCloudBuild, + }, } } // Convert converts a message off the pubsub format to a source specific if // there's a registered handler for the type in the converters map. // If there's no registered handler, a default Pubsub one will be used. -func Convert(ctx context.Context, msg *pubsub.Message, converterType string) (*cev2.Event, error) { +func (c *PubSubConverter) Convert(ctx context.Context, msg *pubsub.Message, converterType string) (*cev2.Event, error) { if msg == nil { return nil, fmt.Errorf("nil pubsub message") } // Try the converterType, if specified. if converterType != "" { - if c, ok := converters[converterType]; ok { + if c, ok := c.converters[converterType]; ok { return c(ctx, msg) } } @@ -78,7 +86,7 @@ func Convert(ctx context.Context, msg *pubsub.Message, converterType string) (*c if msg.Attributes != nil { if val, ok := msg.Attributes[KnativeGCPConverter]; ok { delete(msg.Attributes, KnativeGCPConverter) - if c, ok := converters[val]; ok { + if c, ok := c.converters[val]; ok { return c(ctx, msg) } } diff --git a/pkg/pubsub/adapter/converters/pubsub_test.go b/pkg/pubsub/adapter/converters/pubsub_test.go index 7eea42f6c4..5a6e956b57 100644 --- a/pkg/pubsub/adapter/converters/pubsub_test.go +++ b/pkg/pubsub/adapter/converters/pubsub_test.go @@ -70,7 +70,7 @@ func TestConvertCloudPubSub(t *testing.T) { ctx = WithTopicKey(ctx, "testtopic") ctx = WithSubscriptionKey(ctx, "testsubscription") - gotEvent, err := Convert(ctx, test.message, "") + gotEvent, err := NewPubSubConverter().Convert(ctx, test.message, "") if err != nil { if !test.wantErr { t.Errorf("converters.convertPubsub got error %v want error=%v", err, test.wantErr) diff --git a/pkg/pubsub/adapter/converters/scheduler_test.go b/pkg/pubsub/adapter/converters/scheduler_test.go index 82b15b3b2f..9666455614 100644 --- a/pkg/pubsub/adapter/converters/scheduler_test.go +++ b/pkg/pubsub/adapter/converters/scheduler_test.go @@ -83,7 +83,7 @@ func TestConvertCloudSchedulerSource(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - gotEvent, err := Convert(context.Background(), test.message, "") + gotEvent, err := NewPubSubConverter().Convert(context.Background(), test.message, "") if test.wantErr != "" || err != nil { var gotErr string diff --git a/pkg/pubsub/adapter/converters/storage_test.go b/pkg/pubsub/adapter/converters/storage_test.go index 39cacb2c1e..81aea6344f 100644 --- a/pkg/pubsub/adapter/converters/storage_test.go +++ b/pkg/pubsub/adapter/converters/storage_test.go @@ -134,7 +134,7 @@ func TestConvertCloudStorageSource(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - gotEvent, err := Convert(context.Background(), test.message, "") + gotEvent, err := NewPubSubConverter().Convert(context.Background(), test.message, "") if err != nil { if !test.wantErr { diff --git a/pkg/pubsub/adapter/providers.go b/pkg/pubsub/adapter/providers.go index 7f46f50f12..be8a0da0c4 100644 --- a/pkg/pubsub/adapter/providers.go +++ b/pkg/pubsub/adapter/providers.go @@ -4,6 +4,7 @@ import ( "context" "cloud.google.com/go/pubsub" + "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "github.com/google/knative-gcp/pkg/utils/clients" "github.com/google/wire" ) @@ -24,6 +25,7 @@ var AdapterSet wire.ProviderSet = wire.NewSet( NewAdapter, clients.NewPubsubClient, NewPubSubSubscription, + converters.NewPubSubConverter, NewStatsReporter, clients.NewHTTPClient, ) From d0afb5cbedd50cb46b346e6d2dd6114eaf1293d3 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Wed, 17 Jun 2020 16:50:42 -0700 Subject: [PATCH 05/28] update --- cmd/pubsub/receive_adapter/main.go | 6 ++++ pkg/pubsub/adapter/adapter.go | 57 +++++++++++++++++++----------- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/cmd/pubsub/receive_adapter/main.go b/cmd/pubsub/receive_adapter/main.go index f2d454b7ed..ecf825907c 100644 --- a/cmd/pubsub/receive_adapter/main.go +++ b/cmd/pubsub/receive_adapter/main.go @@ -52,6 +52,12 @@ type envConfig struct { Sink string `envconfig:"SINK_URI" required:"true"` // Environment variable containing the transformer URI. + // This environment variable is only set if we configure both subscriber and reply + // in Channel's subscribers. + // If subscriber and reply are used, we map: + // Transformer to sub.subscriber + // Sink to sub.reply + // Otherwise, only Sink is used (for either the sub.reply or sub.reply) Transformer string `envconfig:"TRANSFORMER_URI"` // Environment variable specifying the type of adapter to use. diff --git a/pkg/pubsub/adapter/adapter.go b/pkg/pubsub/adapter/adapter.go index eab1ecd32f..49d762f7a2 100644 --- a/pkg/pubsub/adapter/adapter.go +++ b/pkg/pubsub/adapter/adapter.go @@ -52,6 +52,7 @@ type Adapter struct { // extensions is the converted ExtensionsBased64 value. extensions map[string]string + // adapterType use to select which converter to use. adapterType string // reporter reports metrics to the configured backend. @@ -60,6 +61,9 @@ type Adapter struct { // converter used to convert pubsub messages to CE. converter converters.Converter + // cancel is function to stop pulling messages. + cancel context.CancelFunc + logger *zap.Logger } @@ -88,8 +92,8 @@ func NewAdapter( } func (a *Adapter) Start(ctx context.Context) error { - ctx, cancel := context.WithCancel(ctx) - defer cancel() + ctx, a.cancel = context.WithCancel(ctx) + defer a.cancel() errCh := make(chan error, 1) go func() { @@ -106,7 +110,7 @@ func (a *Adapter) Start(ctx context.Context) error { // Done channel has been closed, we need to gracefully shutdown. The cancel() method will start its // shutdown, if it hasn't finished in a reasonable amount of time, just return an error. - cancel() + a.cancel() select { case err := <-errCh: return err @@ -115,6 +119,13 @@ func (a *Adapter) Start(ctx context.Context) error { } } +// Stop stops the adapter. +func (a *Adapter) Stop() { + a.cancel() +} + +// TODO refactor this method. As our RA code is used both for Sources and our Channel, it also supports replies +// (in the case of Channels) and the logic is more convoluted. func (a *Adapter) receive(ctx context.Context, msg *pubsub.Message) { event, err := a.converter.Convert(ctx, msg, a.adapterType) if err != nil { @@ -124,24 +135,20 @@ func (a *Adapter) receive(ctx context.Context, msg *pubsub.Message) { return } - // Apply CloudEvent override extensions to the outbound event. - for k, v := range a.extensions { - event.SetExtension(k, v) - } - args := &ReportArgs{ EventType: event.Type(), EventSource: event.Source(), } - message := (*binding.EventMessage)(event) + // Using this variable to check whether the event came from a reply or not. + reply := false - // If a transformer has been configured, then transform the message. - // Note that this path in the code will be executed when using the receive adapter as part of the underlying Channel - // of a Broker. We currently set the TransformerURI to be the address of the Broker filter pod. - // TODO consider renaming transformer as it is confusing. And see if we can get rid of this. + // If a transformer has been configured, then "transform" the message. + // Note that currently this path of the code will be executed when using the receive adapter as part of the underlying Channel, + // in case both subscriber and reply are set. The transformer would act as the subscriber and the sink will be where + // we will send the reply. if a.transformerURI != "" { - resp, err := a.sendMsg(ctx, a.transformerURI, message) + resp, err := a.sendMsg(ctx, a.transformerURI, (*binding.EventMessage)(event)) if err != nil { a.logger.Error("Failed to send message to transformer", zap.String("address", a.transformerURI), zap.Error(err)) msg.Nack() @@ -164,12 +171,14 @@ func (a *Adapter) receive(ctx context.Context, msg *pubsub.Message) { respMsg := cehttp.NewMessageFromHttpResponse(resp) if respMsg.ReadEncoding() == binding.EncodingUnknown { - // This doesn't mean there was an error. E.g., the Broker filter pod might not return a response. + // No reply msg.Ack() return } - e, err := binding.ToEvent(ctx, respMsg) + // If there was a reply, we need to send it to the sink. + // We then overwrite the initial event we sent. + event, err = binding.ToEvent(ctx, respMsg) if err != nil { a.logger.Error("Failed to convert response message to event", zap.Any("response", respMsg), zap.Error(err)) @@ -181,16 +190,24 @@ func (a *Adapter) receive(ctx context.Context, msg *pubsub.Message) { // Update the tracing information to use the span returned by the transformer. // ctx = trace.NewContext(ctx, trace.FromContext(transformedCTX)) if span := trace.FromContext(ctx); span.IsRecordingEvents() { - span.Annotate(ceclient.EventTraceAttributes(e), + span.Annotate(ceclient.EventTraceAttributes(event), "Event reply", ) } - // Update the message with the transformed one. - message = (*binding.EventMessage)(e) + reply = true + } + + // Only if the message is not from a reply, then we should add the override extensions. + if !reply { + // Apply CloudEvent override extensions to the outbound event. + // This code will be mainly executed by Sources. + for k, v := range a.extensions { + event.SetExtension(k, v) + } } - resp, err := a.sendMsg(ctx, a.sinkURI, message) + resp, err := a.sendMsg(ctx, a.sinkURI, (*binding.EventMessage)(event)) if err != nil { a.logger.Error("Failed to send message to sink", zap.String("address", a.sinkURI), zap.Error(err)) msg.Nack() From 06eb40697875e7e68b25050ba93cd03f78496941 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Wed, 17 Jun 2020 18:42:02 -0700 Subject: [PATCH 06/28] fixing storage --- pkg/pubsub/adapter/converters/storage.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/pubsub/adapter/converters/storage.go b/pkg/pubsub/adapter/converters/storage.go index a89041ed78..ceb6b8212b 100644 --- a/pkg/pubsub/adapter/converters/storage.go +++ b/pkg/pubsub/adapter/converters/storage.go @@ -69,7 +69,7 @@ func convertCloudStorage(ctx context.Context, msg *pubsub.Message) (*cev2.Event, return nil, errors.New("received event did not have eventType") } - if err := event.SetData(cev2.ApplicationJSON, msg); err != nil { + if err := event.SetData(cev2.ApplicationJSON, msg.Data); err != nil { return nil, err } return &event, nil From 4a9b3cbbb1b193317b6c3eb2c5309ea52cc63aec Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Wed, 17 Jun 2020 23:46:10 -0700 Subject: [PATCH 07/28] using converter type for every source instead of just some. channel and pullsubscription won't have any, thus default to regular pubsub --- cmd/pubsub/receive_adapter/main.go | 4 +- cmd/pubsub/receive_adapter/wire.go | 3 +- cmd/pubsub/receive_adapter/wire_gen.go | 4 +- pkg/pubsub/adapter/adapter.go | 10 ++-- pkg/pubsub/adapter/converters/auditlogs.go | 2 - .../adapter/converters/auditlogs_test.go | 4 +- pkg/pubsub/adapter/converters/build.go | 1 - pkg/pubsub/adapter/converters/build_test.go | 9 ++-- pkg/pubsub/adapter/converters/converters.go | 52 ++++++++++--------- pkg/pubsub/adapter/converters/pubsub.go | 2 +- pkg/pubsub/adapter/converters/pubsub_test.go | 2 +- pkg/pubsub/adapter/converters/scheduler.go | 4 -- .../adapter/converters/scheduler_test.go | 4 +- pkg/pubsub/adapter/converters/storage.go | 1 - pkg/pubsub/adapter/converters/storage_test.go | 40 ++++++-------- pkg/pubsub/adapter/providers.go | 1 - .../events/auditlogs/auditlogs_test.go | 34 +++++++----- pkg/reconciler/events/auditlogs/controller.go | 8 ++- pkg/reconciler/events/build/build.go | 4 +- pkg/reconciler/events/build/build_test.go | 17 ++++-- pkg/reconciler/events/build/controller.go | 8 ++- pkg/reconciler/events/pubsub/controller.go | 9 +++- pkg/reconciler/events/pubsub/pubsub.go | 2 +- pkg/reconciler/events/pubsub/pubsub_test.go | 19 ++++--- pkg/reconciler/events/scheduler/controller.go | 9 +++- pkg/reconciler/events/scheduler/scheduler.go | 4 +- .../events/scheduler/scheduler_test.go | 21 +++++++- pkg/reconciler/events/storage/controller.go | 9 +++- pkg/reconciler/events/storage/storage.go | 7 --- pkg/reconciler/events/storage/storage_test.go | 20 ++++++- pkg/reconciler/intevents/controller.go | 20 ++++--- pkg/reconciler/intevents/controller_test.go | 8 ++- .../resources/receive_adapter_test.go | 4 +- pkg/reconciler/intevents/reconciler.go | 14 +++-- 34 files changed, 215 insertions(+), 145 deletions(-) diff --git a/cmd/pubsub/receive_adapter/main.go b/cmd/pubsub/receive_adapter/main.go index ecf825907c..f242874975 100644 --- a/cmd/pubsub/receive_adapter/main.go +++ b/cmd/pubsub/receive_adapter/main.go @@ -28,6 +28,7 @@ import ( metadataClient "github.com/google/knative-gcp/pkg/gclient/metadata" . "github.com/google/knative-gcp/pkg/pubsub/adapter" "github.com/google/knative-gcp/pkg/pubsub/adapter/context" + "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" tracingconfig "github.com/google/knative-gcp/pkg/tracing" "github.com/google/knative-gcp/pkg/utils" "github.com/google/knative-gcp/pkg/utils/appcredentials" @@ -61,6 +62,7 @@ type envConfig struct { Transformer string `envconfig:"TRANSFORMER_URI"` // Environment variable specifying the type of adapter to use. + // Used for CE conversion. AdapterType string `envconfig:"ADAPTER_TYPE"` // Topic is the environment variable containing the PubSub Topic being @@ -174,7 +176,7 @@ func main() { Name(env.Name), Namespace(env.Namespace), ResourceGroup(env.ResourceGroup), - AdapterType(env.AdapterType), + converters.ConverterType(env.AdapterType), SinkURI(env.Sink), TransformerURI(env.Transformer), extensions) diff --git a/cmd/pubsub/receive_adapter/wire.go b/cmd/pubsub/receive_adapter/wire.go index b598bd71cc..05f4795f95 100644 --- a/cmd/pubsub/receive_adapter/wire.go +++ b/cmd/pubsub/receive_adapter/wire.go @@ -22,6 +22,7 @@ import ( "context" "github.com/google/knative-gcp/pkg/pubsub/adapter" + "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "github.com/google/knative-gcp/pkg/utils/clients" "github.com/google/wire" @@ -35,7 +36,7 @@ func InitializeAdapter( name adapter.Name, namespace adapter.Namespace, resourceGroup adapter.ResourceGroup, - adapterType adapter.AdapterType, + converterType converters.ConverterType, sinkURI adapter.SinkURI, transformerURI adapter.TransformerURI, extensions map[string]string, diff --git a/cmd/pubsub/receive_adapter/wire_gen.go b/cmd/pubsub/receive_adapter/wire_gen.go index 6cafa424d7..8ffb484afa 100644 --- a/cmd/pubsub/receive_adapter/wire_gen.go +++ b/cmd/pubsub/receive_adapter/wire_gen.go @@ -14,7 +14,7 @@ import ( // Injectors from wire.go: -func InitializeAdapter(ctx context.Context, projectID clients.ProjectID, subscription adapter.SubscriptionID, maxConnsPerHost clients.MaxConnsPerHost, name adapter.Name, namespace adapter.Namespace, resourceGroup adapter.ResourceGroup, adapterType adapter.AdapterType, sinkURI adapter.SinkURI, transformerURI adapter.TransformerURI, extensions map[string]string) (*adapter.Adapter, error) { +func InitializeAdapter(ctx context.Context, projectID clients.ProjectID, subscription adapter.SubscriptionID, maxConnsPerHost clients.MaxConnsPerHost, name adapter.Name, namespace adapter.Namespace, resourceGroup adapter.ResourceGroup, converterType converters.ConverterType, sinkURI adapter.SinkURI, transformerURI adapter.TransformerURI, extensions map[string]string) (*adapter.Adapter, error) { client, err := clients.NewPubsubClient(ctx, projectID) if err != nil { return nil, err @@ -26,6 +26,6 @@ func InitializeAdapter(ctx context.Context, projectID clients.ProjectID, subscri if err != nil { return nil, err } - adapterAdapter := adapter.NewAdapter(ctx, pubsubSubscription, httpClient, converter, statsReporter, sinkURI, transformerURI, adapterType, extensions) + adapterAdapter := adapter.NewAdapter(ctx, pubsubSubscription, httpClient, converter, statsReporter, sinkURI, transformerURI, converterType, extensions) return adapterAdapter, nil } diff --git a/pkg/pubsub/adapter/adapter.go b/pkg/pubsub/adapter/adapter.go index 49d762f7a2..a9fa203179 100644 --- a/pkg/pubsub/adapter/adapter.go +++ b/pkg/pubsub/adapter/adapter.go @@ -52,8 +52,8 @@ type Adapter struct { // extensions is the converted ExtensionsBased64 value. extensions map[string]string - // adapterType use to select which converter to use. - adapterType string + // converterType use to select which converter to use. + converterType converters.ConverterType // reporter reports metrics to the configured backend. reporter StatsReporter @@ -76,7 +76,7 @@ func NewAdapter( reporter StatsReporter, sinkURI SinkURI, transformerURI TransformerURI, - adapterType AdapterType, + converterType converters.ConverterType, extensions map[string]string) *Adapter { return &Adapter{ subscription: subscription, @@ -85,7 +85,7 @@ func NewAdapter( reporter: reporter, sinkURI: string(sinkURI), transformerURI: string(transformerURI), - adapterType: string(adapterType), + converterType: converterType, extensions: extensions, logger: logging.FromContext(ctx), } @@ -127,7 +127,7 @@ func (a *Adapter) Stop() { // TODO refactor this method. As our RA code is used both for Sources and our Channel, it also supports replies // (in the case of Channels) and the logic is more convoluted. func (a *Adapter) receive(ctx context.Context, msg *pubsub.Message) { - event, err := a.converter.Convert(ctx, msg, a.adapterType) + event, err := a.converter.Convert(ctx, msg, a.converterType) if err != nil { a.logger.Debug("Failed to convert received message to an event, check the msg format: %w", zap.Error(err)) // Ack the message so it won't be retried diff --git a/pkg/pubsub/adapter/converters/auditlogs.go b/pkg/pubsub/adapter/converters/auditlogs.go index 8556f3c5f5..0bbdfb315d 100644 --- a/pkg/pubsub/adapter/converters/auditlogs.go +++ b/pkg/pubsub/adapter/converters/auditlogs.go @@ -39,8 +39,6 @@ import ( ) const ( - CloudAuditLogsConverter = "com.google.cloud.auditlogs" - logEntrySchema = "type.googleapis.com/google.logging.v2.LogEntry" parentResourcePattern = `^(:?projects|organizations|billingAccounts|folders)/[^/]+` diff --git a/pkg/pubsub/adapter/converters/auditlogs_test.go b/pkg/pubsub/adapter/converters/auditlogs_test.go index e4069079f9..0f79659b08 100644 --- a/pkg/pubsub/adapter/converters/auditlogs_test.go +++ b/pkg/pubsub/adapter/converters/auditlogs_test.go @@ -76,7 +76,7 @@ func TestConvertAuditLog(t *testing.T) { Data: buf.Bytes(), } - e, err := NewPubSubConverter().Convert(context.Background(), &msg, CloudAuditLogsConverter) + e, err := NewPubSubConverter().Convert(context.Background(), &msg, CloudAuditLogs) if err != nil { t.Fatalf("conversion failed: %v", err) @@ -144,7 +144,7 @@ func TestConvertTextPayload(t *testing.T) { Data: buf.Bytes(), } - _, err = NewPubSubConverter().Convert(context.Background(), &msg, CloudAuditLogsConverter) + _, err = NewPubSubConverter().Convert(context.Background(), &msg, CloudAuditLogs) if err == nil { t.Errorf("Expected error when converting non-AuditLog LogEntry.") diff --git a/pkg/pubsub/adapter/converters/build.go b/pkg/pubsub/adapter/converters/build.go index da09db9780..c61820ceb0 100644 --- a/pkg/pubsub/adapter/converters/build.go +++ b/pkg/pubsub/adapter/converters/build.go @@ -27,7 +27,6 @@ import ( ) const ( - CloudBuildConverter = "com.google.cloud.build" buildSchemaUrl = "https://raw.githubusercontent.com/google/knative-gcp/master/schemas/build/schema.json" ) diff --git a/pkg/pubsub/adapter/converters/build_test.go b/pkg/pubsub/adapter/converters/build_test.go index 6e8ebb970e..7944c40c7c 100644 --- a/pkg/pubsub/adapter/converters/build_test.go +++ b/pkg/pubsub/adapter/converters/build_test.go @@ -56,10 +56,7 @@ func TestConvertCloudBuild(t *testing.T) { }, }, wantEventFn: func() *cev2.Event { - return buildCloudEvent(map[string]string{ - "buildId": buildID, - "status": buildStatus, - }, buildID, buildStatus) + return buildCloudEvent(buildID, buildStatus) }, }, { @@ -95,7 +92,7 @@ func TestConvertCloudBuild(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { ctx := WithProjectKey(context.Background(), "testproject") - gotEvent, err := NewPubSubConverter().Convert(ctx, test.message, CloudBuildConverter) + gotEvent, err := NewPubSubConverter().Convert(ctx, test.message, CloudBuild) if err != nil { if !test.wantErr { t.Errorf("converters.convertBuild got error %v want error=%v", err, test.wantErr) @@ -124,7 +121,7 @@ func TestConvertCloudBuild(t *testing.T) { } } -func buildCloudEvent(extensions map[string]string, buildID, buildStatus string) *cev2.Event { +func buildCloudEvent(buildID, buildStatus string) *cev2.Event { e := cev2.NewEvent(cev2.VersionV1) e.SetID("id") e.SetTime(buildPublishTime) diff --git a/pkg/pubsub/adapter/converters/converters.go b/pkg/pubsub/adapter/converters/converters.go index cd23be6bf7..9116d8c229 100644 --- a/pkg/pubsub/adapter/converters/converters.go +++ b/pkg/pubsub/adapter/converters/converters.go @@ -23,7 +23,9 @@ import ( "fmt" "cloud.google.com/go/pubsub" + cepubsub "github.com/cloudevents/sdk-go/protocol/pubsub/v2" cev2 "github.com/cloudevents/sdk-go/v2" + "github.com/cloudevents/sdk-go/v2/binding" ) // ModeType is the type for mode enum. @@ -38,33 +40,43 @@ const ( Push ModeType = "push" // DefaultSendMode is the default choice. DefaultSendMode = Binary - // The key used in the message attributes which defines the converter type. - KnativeGCPConverter = "knative-gcp" +) + +type ConverterType string + +const ( + // The different type of Converters for the different sources. + CloudPubSub ConverterType = "pubsub" + CloudStorage ConverterType = "storage" + CloudAuditLogs ConverterType = "auditlogs" + CloudScheduler ConverterType = "scheduler" + CloudBuild ConverterType = "build" ) type converterFn func(context.Context, *pubsub.Message) (*cev2.Event, error) type Converter interface { - Convert(ctx context.Context, msg *pubsub.Message, converterType string) (*cev2.Event, error) + Convert(ctx context.Context, msg *pubsub.Message, converterType ConverterType) (*cev2.Event, error) } type PubSubConverter struct { // converters is the map for handling Source specific event // conversions. For example, a GCS event will need to be - // converted differently from the PubSub. The key into - // this map will be "knative-gcp" CloudEvent attribute. - // If there's no such attribute, we assume it's a native - // PubSub message and a default one will be used. - converters map[string]converterFn + // converted differently than a PubSub one. The key into + // this map will be the adapter type. If not present, + // we assume it's a native PubSub message and a default + // one will be used. + converters map[ConverterType]converterFn } func NewPubSubConverter() Converter { return &PubSubConverter{ - converters: map[string]converterFn{ - CloudAuditLogsConverter: convertCloudAuditLogs, - CloudStorageConverter: convertCloudStorage, - CloudSchedulerConverter: convertCloudScheduler, - CloudBuildConverter: convertCloudBuild, + converters: map[ConverterType]converterFn{ + CloudPubSub: convertCloudPubSub, + CloudAuditLogs: convertCloudAuditLogs, + CloudStorage: convertCloudStorage, + CloudScheduler: convertCloudScheduler, + CloudBuild: convertCloudBuild, }, } } @@ -72,7 +84,7 @@ func NewPubSubConverter() Converter { // Convert converts a message off the pubsub format to a source specific if // there's a registered handler for the type in the converters map. // If there's no registered handler, a default Pubsub one will be used. -func (c *PubSubConverter) Convert(ctx context.Context, msg *pubsub.Message, converterType string) (*cev2.Event, error) { +func (c *PubSubConverter) Convert(ctx context.Context, msg *pubsub.Message, converterType ConverterType) (*cev2.Event, error) { if msg == nil { return nil, fmt.Errorf("nil pubsub message") } @@ -82,16 +94,8 @@ func (c *PubSubConverter) Convert(ctx context.Context, msg *pubsub.Message, conv return c(ctx, msg) } } - // Try the generic KnativeGCPConverter attribute, if present. - if msg.Attributes != nil { - if val, ok := msg.Attributes[KnativeGCPConverter]; ok { - delete(msg.Attributes, KnativeGCPConverter) - if c, ok := c.converters[val]; ok { - return c(ctx, msg) - } - } - } // No converter, PubSub is the default one. - return convertPubSub(ctx, msg) + return binding.ToEvent(ctx, cepubsub.NewMessage(msg)) + } diff --git a/pkg/pubsub/adapter/converters/pubsub.go b/pkg/pubsub/adapter/converters/pubsub.go index bb48003807..8fbf6b94f6 100644 --- a/pkg/pubsub/adapter/converters/pubsub.go +++ b/pkg/pubsub/adapter/converters/pubsub.go @@ -26,7 +26,7 @@ import ( . "github.com/google/knative-gcp/pkg/pubsub/adapter/context" ) -func convertPubSub(ctx context.Context, msg *pubsub.Message) (*cev2.Event, error) { +func convertCloudPubSub(ctx context.Context, msg *pubsub.Message) (*cev2.Event, error) { event := cev2.NewEvent(cev2.VersionV1) event.SetID(msg.ID) event.SetTime(msg.PublishTime) diff --git a/pkg/pubsub/adapter/converters/pubsub_test.go b/pkg/pubsub/adapter/converters/pubsub_test.go index 5a6e956b57..5943a815e3 100644 --- a/pkg/pubsub/adapter/converters/pubsub_test.go +++ b/pkg/pubsub/adapter/converters/pubsub_test.go @@ -70,7 +70,7 @@ func TestConvertCloudPubSub(t *testing.T) { ctx = WithTopicKey(ctx, "testtopic") ctx = WithSubscriptionKey(ctx, "testsubscription") - gotEvent, err := NewPubSubConverter().Convert(ctx, test.message, "") + gotEvent, err := NewPubSubConverter().Convert(ctx, test.message, CloudPubSub) if err != nil { if !test.wantErr { t.Errorf("converters.convertPubsub got error %v want error=%v", err, test.wantErr) diff --git a/pkg/pubsub/adapter/converters/scheduler.go b/pkg/pubsub/adapter/converters/scheduler.go index bc3c672922..124ec1ea02 100644 --- a/pkg/pubsub/adapter/converters/scheduler.go +++ b/pkg/pubsub/adapter/converters/scheduler.go @@ -27,10 +27,6 @@ import ( cev2 "github.com/cloudevents/sdk-go/v2" ) -const ( - CloudSchedulerConverter = "com.google.cloud.scheduler" -) - func convertCloudScheduler(ctx context.Context, msg *pubsub.Message) (*cev2.Event, error) { event := cev2.NewEvent(cev2.VersionV1) event.SetID(msg.ID) diff --git a/pkg/pubsub/adapter/converters/scheduler_test.go b/pkg/pubsub/adapter/converters/scheduler_test.go index 9666455614..7ec5a4fa90 100644 --- a/pkg/pubsub/adapter/converters/scheduler_test.go +++ b/pkg/pubsub/adapter/converters/scheduler_test.go @@ -39,7 +39,7 @@ func TestConvertCloudSchedulerSource(t *testing.T) { }{{ name: "valid attributes", message: &pubsub.Message{ - ID: "id", + ID: "id", Data: []byte("test data"), Attributes: map[string]string{ "knative-gcp": "com.google.cloud.scheduler", @@ -83,7 +83,7 @@ func TestConvertCloudSchedulerSource(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - gotEvent, err := NewPubSubConverter().Convert(context.Background(), test.message, "") + gotEvent, err := NewPubSubConverter().Convert(context.Background(), test.message, CloudScheduler) if test.wantErr != "" || err != nil { var gotErr string diff --git a/pkg/pubsub/adapter/converters/storage.go b/pkg/pubsub/adapter/converters/storage.go index ceb6b8212b..a8ea5c8a26 100644 --- a/pkg/pubsub/adapter/converters/storage.go +++ b/pkg/pubsub/adapter/converters/storage.go @@ -40,7 +40,6 @@ const ( // TODO find the public google endpoint we should use to point to the schema and avoid hosting it ourselves. // The link above is tied to the go-client, and it seems not to be a valid json schema. storageSchemaUrl = "https://raw.githubusercontent.com/google/knative-gcp/master/schemas/storage/schema.json" - CloudStorageConverter = "com.google.cloud.storage" ) func convertCloudStorage(ctx context.Context, msg *pubsub.Message) (*cev2.Event, error) { diff --git a/pkg/pubsub/adapter/converters/storage_test.go b/pkg/pubsub/adapter/converters/storage_test.go index 81aea6344f..4128dc5600 100644 --- a/pkg/pubsub/adapter/converters/storage_test.go +++ b/pkg/pubsub/adapter/converters/storage_test.go @@ -48,9 +48,6 @@ func TestConvertCloudStorageSource(t *testing.T) { name: "no attributes", message: &pubsub.Message{ Data: []byte("test data"), - Attributes: map[string]string{ - "knative-gcp": "com.google.cloud.storage", - }, }, wantEventFn: func() *cev2.Event { return storageCloudEvent() @@ -61,10 +58,9 @@ func TestConvertCloudStorageSource(t *testing.T) { message: &pubsub.Message{ Data: []byte("test data"), Attributes: map[string]string{ - "knative-gcp": "com.google.cloud.storage", - "eventType": eventType, - "attribute1": "value1", - "attribute2": "value2", + "eventType": eventType, + "attribute1": "value1", + "attribute2": "value2", }, }, wantEventFn: func() *cev2.Event { @@ -76,9 +72,8 @@ func TestConvertCloudStorageSource(t *testing.T) { message: &pubsub.Message{ Data: []byte("test data"), Attributes: map[string]string{ - "knative-gcp": "com.google.cloud.storage", - "bucketId": bucket, - "objectId": objectId, + "bucketId": bucket, + "objectId": objectId, }, }, wantEventFn: func() *cev2.Event { @@ -90,10 +85,9 @@ func TestConvertCloudStorageSource(t *testing.T) { message: &pubsub.Message{ Data: []byte("test data"), Attributes: map[string]string{ - "knative-gcp": "com.google.cloud.storage", - "eventType": "RANDOM_EVENT", - "bucketId": bucket, - "objectId": objectId, + "eventType": "RANDOM_EVENT", + "bucketId": bucket, + "objectId": objectId, }, }, wantEventFn: func() *cev2.Event { @@ -105,9 +99,8 @@ func TestConvertCloudStorageSource(t *testing.T) { message: &pubsub.Message{ Data: []byte("test data"), Attributes: map[string]string{ - "knative-gcp": "com.google.cloud.storage", - "bucketId": bucket, - "eventType": eventType, + "bucketId": bucket, + "eventType": eventType, }, }, wantEventFn: func() *cev2.Event { @@ -117,14 +110,13 @@ func TestConvertCloudStorageSource(t *testing.T) { }, { name: "valid message", message: &pubsub.Message{ - ID: "id", + ID: "id", PublishTime: storagePublishTime, - Data: []byte("test data"), + Data: []byte("test data"), Attributes: map[string]string{ - "knative-gcp": "com.google.cloud.storage", - "bucketId": bucket, - "eventType": eventType, - "objectId": objectId, + "bucketId": bucket, + "eventType": eventType, + "objectId": objectId, }, }, wantEventFn: func() *cev2.Event { @@ -134,7 +126,7 @@ func TestConvertCloudStorageSource(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - gotEvent, err := NewPubSubConverter().Convert(context.Background(), test.message, "") + gotEvent, err := NewPubSubConverter().Convert(context.Background(), test.message, CloudStorage) if err != nil { if !test.wantErr { diff --git a/pkg/pubsub/adapter/providers.go b/pkg/pubsub/adapter/providers.go index be8a0da0c4..2056b388e6 100644 --- a/pkg/pubsub/adapter/providers.go +++ b/pkg/pubsub/adapter/providers.go @@ -14,7 +14,6 @@ import ( type Name string type Namespace string type ResourceGroup string -type AdapterType string type SinkURI string type TransformerURI string diff --git a/pkg/reconciler/events/auditlogs/auditlogs_test.go b/pkg/reconciler/events/auditlogs/auditlogs_test.go index 76f98cbd74..bccecc0742 100644 --- a/pkg/reconciler/events/auditlogs/auditlogs_test.go +++ b/pkg/reconciler/events/auditlogs/auditlogs_test.go @@ -471,7 +471,7 @@ func TestAllCases(t *testing.T) { PubSubSpec: duckv1beta1.PubSubSpec{ Secret: &secret, }, - AdapterType: converters.CloudAuditLogsConverter, + AdapterType: string(converters.CloudAuditLogs), }), WithPullSubscriptionSink(sinkGVK, sinkName), WithPullSubscriptionLabels(map[string]string{ @@ -479,7 +479,7 @@ func TestAllCases(t *testing.T) { "events.cloud.google.com/source-name": sourceName, }), WithPullSubscriptionAnnotations(map[string]string{ - "metrics-resource-group": resourceGroup, + "metrics-resource-group": resourceGroup, duckv1beta1.ClusterNameAnnotation: testingMetadataClient.FakeClusterName, }), WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{sourceOwnerRef(sourceName, sourceUID)}), @@ -521,7 +521,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, - AdapterType: converters.CloudAuditLogsConverter, + AdapterType: string(converters.CloudAuditLogs), })), }, Key: testNS + "/" + sourceName, @@ -572,7 +572,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, - AdapterType: converters.CloudAuditLogsConverter, + AdapterType: string(converters.CloudAuditLogs), })), }, Key: testNS + "/" + sourceName, @@ -623,7 +623,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, - AdapterType: converters.CloudAuditLogsConverter, + AdapterType: string(converters.CloudAuditLogs), })), }, Key: testNS + "/" + sourceName, @@ -675,7 +675,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, - AdapterType: converters.CloudAuditLogsConverter, + AdapterType: string(converters.CloudAuditLogs), })), }, Key: testNS + "/" + sourceName, @@ -735,7 +735,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, - AdapterType: converters.CloudAuditLogsConverter, + AdapterType: string(converters.CloudAuditLogs), })), }, Key: testNS + "/" + sourceName, @@ -795,7 +795,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, - AdapterType: converters.CloudAuditLogsConverter, + AdapterType: string(converters.CloudAuditLogs), })), }, Key: testNS + "/" + sourceName, @@ -855,7 +855,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, - AdapterType: converters.CloudAuditLogsConverter, + AdapterType: string(converters.CloudAuditLogs), })), }, Key: testNS + "/" + sourceName, @@ -916,7 +916,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, - AdapterType: converters.CloudAuditLogsConverter, + AdapterType: string(converters.CloudAuditLogs), })), }, Key: testNS + "/" + sourceName, @@ -987,7 +987,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, - AdapterType: converters.CloudAuditLogsConverter, + AdapterType: string(converters.CloudAuditLogs), })), }, Key: testNS + "/" + sourceName, @@ -1058,7 +1058,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, - AdapterType: converters.CloudAuditLogsConverter, + AdapterType: string(converters.CloudAuditLogs), })), }, Key: testNS + "/" + sourceName, @@ -1124,7 +1124,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, - AdapterType: converters.CloudAuditLogsConverter, + AdapterType: string(converters.CloudAuditLogs), })), }, Key: testNS + "/" + sourceName, @@ -1338,7 +1338,13 @@ func TestAllCases(t *testing.T) { tt.Test(t, MakeFactory( func(ctx context.Context, listers *Listers, cmw configmap.Watcher, testData map[string]interface{}) controller.Reconciler { r := &Reconciler{ - PubSubBase: intevents.NewPubSubBaseWithAdapter(ctx, controllerAgentName, receiveAdapterName, converters.CloudAuditLogsConverter, cmw), + PubSubBase: intevents.NewPubSubBase(ctx, + &intevents.PubSubBaseArgs{ + ControllerAgentName: controllerAgentName, + ReceiveAdapterName: receiveAdapterName, + ReceiveAdapterType: string(converters.CloudAuditLogs), + ConfigWatcher: cmw, + }), Identity: identity.NewIdentity(ctx, NoopIAMPolicyManager, NewGCPAuthTestStore(t, nil)), auditLogsSourceLister: listers.GetCloudAuditLogsSourceLister(), logadminClientProvider: logadminClientProvider, diff --git a/pkg/reconciler/events/auditlogs/controller.go b/pkg/reconciler/events/auditlogs/controller.go index be33e1140a..3de9790488 100644 --- a/pkg/reconciler/events/auditlogs/controller.go +++ b/pkg/reconciler/events/auditlogs/controller.go @@ -76,7 +76,13 @@ func newController( serviceAccountInformer := serviceaccountinformers.Get(ctx) r := &Reconciler{ - PubSubBase: intevents.NewPubSubBaseWithAdapter(ctx, controllerAgentName, receiveAdapterName, converters.CloudAuditLogsConverter, cmw), + PubSubBase: intevents.NewPubSubBase(ctx, + &intevents.PubSubBaseArgs{ + ControllerAgentName: controllerAgentName, + ReceiveAdapterName: receiveAdapterName, + ReceiveAdapterType: string(converters.CloudAuditLogs), + ConfigWatcher: cmw, + }), Identity: identity.NewIdentity(ctx, ipm, gcpas), auditLogsSourceLister: cloudauditlogssourceInformer.Lister(), logadminClientProvider: glogadmin.NewClient, diff --git a/pkg/reconciler/events/build/build.go b/pkg/reconciler/events/build/build.go index 25a3495a65..192f6bd51b 100644 --- a/pkg/reconciler/events/build/build.go +++ b/pkg/reconciler/events/build/build.go @@ -18,7 +18,6 @@ package build import ( "context" - "github.com/google/knative-gcp/pkg/apis/events" "go.uber.org/zap" @@ -28,6 +27,7 @@ import ( "knative.dev/pkg/logging" pkgreconciler "knative.dev/pkg/reconciler" + "github.com/google/knative-gcp/pkg/apis/events" "github.com/google/knative-gcp/pkg/apis/events/v1beta1" cloudbuildsourcereconciler "github.com/google/knative-gcp/pkg/client/injection/reconciler/events/v1beta1/cloudbuildsource" listers "github.com/google/knative-gcp/pkg/client/listers/events/v1beta1" @@ -72,7 +72,7 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, build *v1beta1.CloudBuil return pkgreconciler.NewEvent(corev1.EventTypeWarning, workloadIdentityFailed, "Failed to reconcile CloudBuildSource workload identity: %s", err.Error()) } } - _, event := r.PubSubBase.ReconcilePullSubscription(ctx, build, events.CloudBuildTopic, resourceGroup, false) + _, event := r.PubSubBase.ReconcilePullSubscription(ctx, build, events.CloudBuildTopic, resourceGroup) if event != nil { return event } diff --git a/pkg/reconciler/events/build/build_test.go b/pkg/reconciler/events/build/build_test.go index b704849a7b..1634008999 100644 --- a/pkg/reconciler/events/build/build_test.go +++ b/pkg/reconciler/events/build/build_test.go @@ -20,9 +20,10 @@ import ( "context" "errors" "fmt" - "github.com/google/knative-gcp/pkg/apis/events" "testing" + "github.com/google/knative-gcp/pkg/apis/events" + "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" corev1 "k8s.io/api/core/v1" apierrs "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -195,6 +196,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, + AdapterType: string(converters.CloudBuild), }), WithPullSubscriptionSink(sinkGVK, sinkName), WithPullSubscriptionLabels(map[string]string{ @@ -202,7 +204,7 @@ func TestAllCases(t *testing.T) { "events.cloud.google.com/source-name": buildName, }), WithPullSubscriptionAnnotations(map[string]string{ - "metrics-resource-group": resourceGroup, + "metrics-resource-group": resourceGroup, duckv1beta1.ClusterNameAnnotation: testingMetadataClient.FakeClusterName, }), WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), @@ -232,6 +234,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, + AdapterType: string(converters.CloudBuild), }), WithPullSubscriptionReadyStatus(corev1.ConditionFalse, "PullSubscriptionFalse", "status false test message")), newSink(), @@ -270,6 +273,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, + AdapterType: string(converters.CloudBuild), }), WithPullSubscriptionReadyStatus(corev1.ConditionUnknown, "PullSubscriptionUnknown", "status unknown test message")), newSink(), @@ -308,6 +312,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, + AdapterType: string(converters.CloudBuild), }), WithPullSubscriptionReady(sinkURI), WithPullSubscriptionReadyStatus(corev1.ConditionTrue, "PullSubscriptionNoReady", ""), @@ -358,7 +363,13 @@ func TestAllCases(t *testing.T) { defer logtesting.ClearAll() table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher, _ map[string]interface{}) controller.Reconciler { r := &Reconciler{ - PubSubBase: intevents.NewPubSubBase(ctx, controllerAgentName, receiveAdapterName, cmw), + PubSubBase: intevents.NewPubSubBase(ctx, + &intevents.PubSubBaseArgs{ + ControllerAgentName: controllerAgentName, + ReceiveAdapterName: receiveAdapterName, + ReceiveAdapterType: string(converters.CloudBuild), + ConfigWatcher: cmw, + }), Identity: identity.NewIdentity(ctx, NoopIAMPolicyManager, NewGCPAuthTestStore(t, nil)), buildLister: listers.GetCloudBuildSourceLister(), serviceAccountLister: listers.GetServiceAccountLister(), diff --git a/pkg/reconciler/events/build/controller.go b/pkg/reconciler/events/build/controller.go index 51dc846ebe..a40a677414 100644 --- a/pkg/reconciler/events/build/controller.go +++ b/pkg/reconciler/events/build/controller.go @@ -67,7 +67,13 @@ func newController( serviceAccountInformer := serviceaccountinformers.Get(ctx) r := &Reconciler{ - PubSubBase: intevents.NewPubSubBaseWithAdapter(ctx, controllerAgentName, receiveAdapterName, converters.CloudBuildConverter, cmw), + PubSubBase: intevents.NewPubSubBase(ctx, + &intevents.PubSubBaseArgs{ + ControllerAgentName: controllerAgentName, + ReceiveAdapterName: receiveAdapterName, + ReceiveAdapterType: string(converters.CloudBuild), + ConfigWatcher: cmw, + }), Identity: identity.NewIdentity(ctx, ipm, gcpas), buildLister: cloudbuildsourceInformer.Lister(), serviceAccountLister: serviceAccountInformer.Lister(), diff --git a/pkg/reconciler/events/pubsub/controller.go b/pkg/reconciler/events/pubsub/controller.go index 81c90ad9f9..5ebfc4ac00 100644 --- a/pkg/reconciler/events/pubsub/controller.go +++ b/pkg/reconciler/events/pubsub/controller.go @@ -31,6 +31,7 @@ import ( cloudpubsubsourceinformers "github.com/google/knative-gcp/pkg/client/injection/informers/events/v1beta1/cloudpubsubsource" pullsubscriptioninformers "github.com/google/knative-gcp/pkg/client/injection/informers/intevents/v1beta1/pullsubscription" cloudpubsubsourcereconciler "github.com/google/knative-gcp/pkg/client/injection/reconciler/events/v1beta1/cloudpubsubsource" + "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "github.com/google/knative-gcp/pkg/reconciler" "github.com/google/knative-gcp/pkg/reconciler/identity" "github.com/google/knative-gcp/pkg/reconciler/identity/iam" @@ -69,7 +70,13 @@ func newController( serviceAccountInformer := serviceaccountinformers.Get(ctx) r := &Reconciler{ - PubSubBase: intevents.NewPubSubBase(ctx, controllerAgentName, receiveAdapterName, cmw), + PubSubBase: intevents.NewPubSubBase(ctx, + &intevents.PubSubBaseArgs{ + ControllerAgentName: controllerAgentName, + ReceiveAdapterName: receiveAdapterName, + ReceiveAdapterType: string(converters.CloudPubSub), + ConfigWatcher: cmw, + }), Identity: identity.NewIdentity(ctx, ipm, gcpas), pubsubLister: cloudpubsubsourceInformer.Lister(), } diff --git a/pkg/reconciler/events/pubsub/pubsub.go b/pkg/reconciler/events/pubsub/pubsub.go index 56216cb636..cfb8ec8172 100644 --- a/pkg/reconciler/events/pubsub/pubsub.go +++ b/pkg/reconciler/events/pubsub/pubsub.go @@ -64,7 +64,7 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, pubsub *v1beta1.CloudPub } } - _, event := r.PubSubBase.ReconcilePullSubscription(ctx, pubsub, pubsub.Spec.Topic, resourceGroup, true) + _, event := r.PubSubBase.ReconcilePullSubscription(ctx, pubsub, pubsub.Spec.Topic, resourceGroup) if event != nil { return event } diff --git a/pkg/reconciler/events/pubsub/pubsub_test.go b/pkg/reconciler/events/pubsub/pubsub_test.go index b21929cef6..76743644b1 100644 --- a/pkg/reconciler/events/pubsub/pubsub_test.go +++ b/pkg/reconciler/events/pubsub/pubsub_test.go @@ -43,6 +43,7 @@ import ( inteventsv1beta1 "github.com/google/knative-gcp/pkg/apis/intevents/v1beta1" "github.com/google/knative-gcp/pkg/client/injection/reconciler/events/v1beta1/cloudpubsubsource" testingMetadataClient "github.com/google/knative-gcp/pkg/gclient/metadata/testing" + "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "github.com/google/knative-gcp/pkg/reconciler/identity" "github.com/google/knative-gcp/pkg/reconciler/intevents" . "github.com/google/knative-gcp/pkg/reconciler/testing" @@ -191,15 +192,15 @@ func TestAllCases(t *testing.T) { PubSubSpec: duckv1beta1.PubSubSpec{ Secret: &secret, }, + AdapterType: string(converters.CloudPubSub), }), WithPullSubscriptionSink(sinkGVK, sinkName), - WithPullSubscriptionMode(inteventsv1beta1.ModePushCompatible), WithPullSubscriptionLabels(map[string]string{ "receive-adapter": receiveAdapterName, "events.cloud.google.com/source-name": pubsubName, }), WithPullSubscriptionAnnotations(map[string]string{ - "metrics-resource-group": resourceGroup, + "metrics-resource-group": resourceGroup, duckv1beta1.ClusterNameAnnotation: testingMetadataClient.FakeClusterName, }), WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), @@ -230,7 +231,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, - Mode: inteventsv1beta1.ModePushCompatible, + AdapterType: string(converters.CloudPubSub), }), WithPullSubscriptionReadyStatus(corev1.ConditionFalse, "PullSubscriptionFalse", "status false test message")), newSink(), @@ -271,7 +272,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, - Mode: inteventsv1beta1.ModePushCompatible, + AdapterType: string(converters.CloudPubSub), }), WithPullSubscriptionReadyStatus(corev1.ConditionUnknown, "PullSubscriptionUnknown", "status unknown test message")), newSink(), @@ -312,7 +313,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, - Mode: inteventsv1beta1.ModePushCompatible, + AdapterType: string(converters.CloudPubSub), }), WithPullSubscriptionReady(sinkURI), WithPullSubscriptionReadyStatus(corev1.ConditionTrue, "PullSubscriptionNoReady", ""), @@ -365,7 +366,13 @@ func TestAllCases(t *testing.T) { defer logtesting.ClearAll() table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher, _ map[string]interface{}) controller.Reconciler { r := &Reconciler{ - PubSubBase: intevents.NewPubSubBase(ctx, controllerAgentName, receiveAdapterName, cmw), + PubSubBase: intevents.NewPubSubBase(ctx, + &intevents.PubSubBaseArgs{ + ControllerAgentName: controllerAgentName, + ReceiveAdapterName: receiveAdapterName, + ReceiveAdapterType: string(converters.CloudPubSub), + ConfigWatcher: cmw, + }), Identity: identity.NewIdentity(ctx, NoopIAMPolicyManager, NewGCPAuthTestStore(t, nil)), pubsubLister: listers.GetCloudPubSubSourceLister(), } diff --git a/pkg/reconciler/events/scheduler/controller.go b/pkg/reconciler/events/scheduler/controller.go index b938195f4e..b25998ac2c 100644 --- a/pkg/reconciler/events/scheduler/controller.go +++ b/pkg/reconciler/events/scheduler/controller.go @@ -23,6 +23,7 @@ import ( "github.com/google/knative-gcp/pkg/apis/configs/gcpauth" "github.com/google/knative-gcp/pkg/apis/events/v1beta1" + "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "github.com/google/knative-gcp/pkg/reconciler" "github.com/google/knative-gcp/pkg/reconciler/identity" "github.com/google/knative-gcp/pkg/reconciler/identity/iam" @@ -72,7 +73,13 @@ func newController( serviceAccountInformer := serviceaccountinformers.Get(ctx) c := &Reconciler{ - PubSubBase: intevents.NewPubSubBase(ctx, controllerAgentName, receiveAdapterName, cmw), + PubSubBase: intevents.NewPubSubBase(ctx, + &intevents.PubSubBaseArgs{ + ControllerAgentName: controllerAgentName, + ReceiveAdapterName: receiveAdapterName, + ReceiveAdapterType: string(converters.CloudScheduler), + ConfigWatcher: cmw, + }), Identity: identity.NewIdentity(ctx, ipm, gcpas), schedulerLister: cloudschedulersourceInformer.Lister(), createClientFn: gscheduler.NewClient, diff --git a/pkg/reconciler/events/scheduler/scheduler.go b/pkg/reconciler/events/scheduler/scheduler.go index fa6b77ba30..0193b46c46 100644 --- a/pkg/reconciler/events/scheduler/scheduler.go +++ b/pkg/reconciler/events/scheduler/scheduler.go @@ -33,7 +33,6 @@ import ( listers "github.com/google/knative-gcp/pkg/client/listers/events/v1beta1" metadataClient "github.com/google/knative-gcp/pkg/gclient/metadata" gscheduler "github.com/google/knative-gcp/pkg/gclient/scheduler" - "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "github.com/google/knative-gcp/pkg/reconciler/events/scheduler/resources" "github.com/google/knative-gcp/pkg/reconciler/identity" "github.com/google/knative-gcp/pkg/reconciler/intevents" @@ -122,9 +121,8 @@ func (r *Reconciler) reconcileJob(ctx context.Context, scheduler *v1beta1.CloudS } else if st.Code() == codes.NotFound { // Create the job as it does not exist. For creation, we need a parent, extract it from the jobName. parent := resources.ExtractParentName(jobName) - // Add our own converter type, jobName, and schedulerName as customAttributes. + // Add our jobName, and schedulerName as customAttributes. customAttributes := map[string]string{ - converters.KnativeGCPConverter: converters.CloudSchedulerConverter, v1beta1.CloudSchedulerSourceJobName: jobName, v1beta1.CloudSchedulerSourceName: scheduler.GetName(), } diff --git a/pkg/reconciler/events/scheduler/scheduler_test.go b/pkg/reconciler/events/scheduler/scheduler_test.go index 6569f50b66..cf2fd1869f 100644 --- a/pkg/reconciler/events/scheduler/scheduler_test.go +++ b/pkg/reconciler/events/scheduler/scheduler_test.go @@ -46,6 +46,7 @@ import ( "github.com/google/knative-gcp/pkg/client/injection/reconciler/events/v1beta1/cloudschedulersource" testingMetadataClient "github.com/google/knative-gcp/pkg/gclient/metadata/testing" gscheduler "github.com/google/knative-gcp/pkg/gclient/scheduler/testing" + "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "github.com/google/knative-gcp/pkg/reconciler/identity" "github.com/google/knative-gcp/pkg/reconciler/intevents" . "github.com/google/knative-gcp/pkg/reconciler/testing" @@ -500,13 +501,14 @@ func TestAllCases(t *testing.T) { PubSubSpec: duckv1beta1.PubSubSpec{ Secret: &secret, }, + AdapterType: string(converters.CloudScheduler), }), WithPullSubscriptionSink(sinkGVK, sinkName), WithPullSubscriptionLabels(map[string]string{ "receive-adapter": receiveAdapterName, SourceLabelKey: schedulerName}), WithPullSubscriptionAnnotations(map[string]string{ - "metrics-resource-group": resourceGroup, + "metrics-resource-group": resourceGroup, duckv1beta1.ClusterNameAnnotation: testingMetadataClient.FakeClusterName, }), WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), @@ -547,6 +549,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, + AdapterType: string(converters.CloudScheduler), })), newSink(), }, @@ -597,6 +600,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, + AdapterType: string(converters.CloudScheduler), })), newSink(), }, @@ -647,6 +651,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, + AdapterType: string(converters.CloudScheduler), })), newSink(), }, @@ -701,6 +706,7 @@ func TestAllCases(t *testing.T) { }, Project: testProject, }, + AdapterType: string(converters.CloudScheduler), }), ), newSink(), @@ -764,6 +770,7 @@ func TestAllCases(t *testing.T) { }, Project: testProject, }, + AdapterType: string(converters.CloudScheduler), }), ), newSink(), @@ -827,6 +834,7 @@ func TestAllCases(t *testing.T) { }, Project: testProject, }, + AdapterType: string(converters.CloudScheduler), }), ), newSink(), @@ -890,6 +898,7 @@ func TestAllCases(t *testing.T) { }, Project: testProject, }, + AdapterType: string(converters.CloudScheduler), }), ), newSink(), @@ -954,6 +963,7 @@ func TestAllCases(t *testing.T) { }, Project: testProject, }, + AdapterType: string(converters.CloudScheduler), }), ), newSink(), @@ -1017,6 +1027,7 @@ func TestAllCases(t *testing.T) { }, Project: testProject, }, + AdapterType: string(converters.CloudScheduler), }), ), newSink(), @@ -1182,7 +1193,13 @@ 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 { r := &Reconciler{ - PubSubBase: intevents.NewPubSubBase(ctx, controllerAgentName, receiveAdapterName, cmw), + PubSubBase: intevents.NewPubSubBase(ctx, + &intevents.PubSubBaseArgs{ + ControllerAgentName: controllerAgentName, + ReceiveAdapterName: receiveAdapterName, + ReceiveAdapterType: string(converters.CloudScheduler), + ConfigWatcher: cmw, + }), Identity: identity.NewIdentity(ctx, NoopIAMPolicyManager, NewGCPAuthTestStore(t, nil)), schedulerLister: listers.GetCloudSchedulerSourceLister(), createClientFn: gscheduler.TestClientCreator(testData["scheduler"]), diff --git a/pkg/reconciler/events/storage/controller.go b/pkg/reconciler/events/storage/controller.go index 4f3b173913..1744a08239 100644 --- a/pkg/reconciler/events/storage/controller.go +++ b/pkg/reconciler/events/storage/controller.go @@ -21,6 +21,7 @@ import ( "knative.dev/pkg/injection" + "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "k8s.io/client-go/tools/cache" serviceaccountinformers "knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount" "knative.dev/pkg/configmap" @@ -72,7 +73,13 @@ func newController( serviceAccountInformer := serviceaccountinformers.Get(ctx) r := &Reconciler{ - PubSubBase: intevents.NewPubSubBase(ctx, controllerAgentName, receiveAdapterName, cmw), + PubSubBase: intevents.NewPubSubBase(ctx, + &intevents.PubSubBaseArgs{ + ControllerAgentName: controllerAgentName, + ReceiveAdapterName: receiveAdapterName, + ReceiveAdapterType: string(converters.CloudStorage), + ConfigWatcher: cmw, + }), Identity: identity.NewIdentity(ctx, ipm, gcpas), storageLister: cloudstoragesourceInformer.Lister(), createClientFn: gstorage.NewClient, diff --git a/pkg/reconciler/events/storage/storage.go b/pkg/reconciler/events/storage/storage.go index 9a627785fd..33e07cca8c 100644 --- a/pkg/reconciler/events/storage/storage.go +++ b/pkg/reconciler/events/storage/storage.go @@ -34,7 +34,6 @@ import ( listers "github.com/google/knative-gcp/pkg/client/listers/events/v1beta1" metadataClient "github.com/google/knative-gcp/pkg/gclient/metadata" gstorage "github.com/google/knative-gcp/pkg/gclient/storage" - "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "github.com/google/knative-gcp/pkg/reconciler/events/storage/resources" "github.com/google/knative-gcp/pkg/reconciler/identity" "github.com/google/knative-gcp/pkg/reconciler/intevents" @@ -152,18 +151,12 @@ func (r *Reconciler) reconcileNotification(ctx context.Context, storage *v1beta1 // If the notification does not exist, then create it. - // Add our own converter type as a customAttribute. - customAttributes := map[string]string{ - converters.KnativeGCPConverter: converters.CloudStorageConverter, - } - nc := &Notification{ TopicProjectID: storage.Status.ProjectID, TopicID: storage.Status.TopicID, PayloadFormat: JSONPayload, EventTypes: r.toCloudStorageSourceEventTypes(storage.Spec.EventTypes), ObjectNamePrefix: storage.Spec.ObjectNamePrefix, - CustomAttributes: customAttributes, } notification, err := bucket.AddNotification(ctx, nc) diff --git a/pkg/reconciler/events/storage/storage_test.go b/pkg/reconciler/events/storage/storage_test.go index ebc748d59f..576a4c6e10 100644 --- a/pkg/reconciler/events/storage/storage_test.go +++ b/pkg/reconciler/events/storage/storage_test.go @@ -48,6 +48,7 @@ import ( "github.com/google/knative-gcp/pkg/client/injection/reconciler/events/v1beta1/cloudstoragesource" testingMetadataClient "github.com/google/knative-gcp/pkg/gclient/metadata/testing" gstorage "github.com/google/knative-gcp/pkg/gclient/storage/testing" + "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "github.com/google/knative-gcp/pkg/reconciler/identity" "github.com/google/knative-gcp/pkg/reconciler/intevents" . "github.com/google/knative-gcp/pkg/reconciler/testing" @@ -492,6 +493,7 @@ func TestAllCases(t *testing.T) { PubSubSpec: duckv1beta1.PubSubSpec{ Secret: &secret, }, + AdapterType: string(converters.CloudStorage), }), WithPullSubscriptionSink(sinkGVK, sinkName), WithPullSubscriptionLabels(map[string]string{ @@ -499,7 +501,7 @@ func TestAllCases(t *testing.T) { SourceLabelKey: storageName, }), WithPullSubscriptionAnnotations(map[string]string{ - "metrics-resource-group": resourceGroup, + "metrics-resource-group": resourceGroup, duckv1beta1.ClusterNameAnnotation: testingMetadataClient.FakeClusterName, }), WithPullSubscriptionOwnerReferences([]metav1.OwnerReference{ownerRef()}), @@ -539,6 +541,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, + AdapterType: string(converters.CloudStorage), })), newSink(), }, @@ -589,6 +592,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, + AdapterType: string(converters.CloudStorage), }), WithPullSubscriptionFailed()), }, Key: testNS + "/" + storageName, @@ -638,6 +642,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, + AdapterType: string(converters.CloudStorage), })), }, Key: testNS + "/" + storageName, @@ -691,6 +696,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, + AdapterType: string(converters.CloudStorage), }), WithPullSubscriptionReady(sinkURI), ), @@ -759,6 +765,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, + AdapterType: string(converters.CloudStorage), }), WithPullSubscriptionReady(sinkURI), ), @@ -828,6 +835,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, + AdapterType: string(converters.CloudStorage), }), WithPullSubscriptionReady(sinkURI), ), @@ -897,6 +905,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, + AdapterType: string(converters.CloudStorage), }), WithPullSubscriptionReady(sinkURI), ), @@ -966,6 +975,7 @@ func TestAllCases(t *testing.T) { Sink: newSinkDestination(), }, }, + AdapterType: string(converters.CloudStorage), }), WithPullSubscriptionReady(sinkURI), ), @@ -1203,7 +1213,13 @@ 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 { r := &Reconciler{ - PubSubBase: intevents.NewPubSubBase(ctx, controllerAgentName, receiveAdapterName, cmw), + PubSubBase: intevents.NewPubSubBase(ctx, + &intevents.PubSubBaseArgs{ + ControllerAgentName: controllerAgentName, + ReceiveAdapterName: receiveAdapterName, + ReceiveAdapterType: string(converters.CloudStorage), + ConfigWatcher: cmw, + }), Identity: identity.NewIdentity(ctx, NoopIAMPolicyManager, NewGCPAuthTestStore(t, nil)), storageLister: listers.GetCloudStorageSourceLister(), createClientFn: gstorage.TestClientCreator(testData["storage"]), diff --git a/pkg/reconciler/intevents/controller.go b/pkg/reconciler/intevents/controller.go index 993fe3f01e..0590fd82c8 100644 --- a/pkg/reconciler/intevents/controller.go +++ b/pkg/reconciler/intevents/controller.go @@ -18,26 +18,24 @@ 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, - } +type PubSubBaseArgs struct { + ControllerAgentName string + ReceiveAdapterName string + ReceiveAdapterType string + ConfigWatcher configmap.Watcher } -func NewPubSubBaseWithAdapter(ctx context.Context, controllerAgentName, receiveAdapterName string, adapterType string, cmw configmap.Watcher) *PubSubBase { +func NewPubSubBase(ctx context.Context, args *PubSubBaseArgs) *PubSubBase { return &PubSubBase{ - Base: reconciler.NewBase(ctx, controllerAgentName, cmw), + Base: reconciler.NewBase(ctx, args.ControllerAgentName, args.ConfigWatcher), pubsubClient: pubsubClient.Get(ctx), - receiveAdapterName: receiveAdapterName, - adapterType: adapterType, + receiveAdapterName: args.ReceiveAdapterName, + receiveAdapterType: args.ReceiveAdapterType, } } diff --git a/pkg/reconciler/intevents/controller_test.go b/pkg/reconciler/intevents/controller_test.go index 98d7a14ce1..5610a99b3b 100644 --- a/pkg/reconciler/intevents/controller_test.go +++ b/pkg/reconciler/intevents/controller_test.go @@ -28,7 +28,13 @@ func TestNew(t *testing.T) { defer logtesting.ClearAll() ctx, _ := SetupFakeContext(t) - c := NewPubSubBase(ctx, "test-controller", "test-ra", configmap.NewStaticWatcher()) + args := &PubSubBaseArgs{ + ControllerAgentName: "test-controller", + ReceiveAdapterName: "test-ra", + ReceiveAdapterType: "test-ra-type", + ConfigWatcher: configmap.NewStaticWatcher(), + } + c := NewPubSubBase(ctx, args) if c == nil { t.Fatal("Expected NewPubSubBase to return a non-nil value") diff --git a/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go b/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go index 14b9a03546..f5749750cc 100644 --- a/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go +++ b/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go @@ -26,7 +26,7 @@ import ( "github.com/google/knative-gcp/pkg/apis/intevents/v1beta1" testingmetadata "github.com/google/knative-gcp/pkg/gclient/metadata/testing" - v1 "k8s.io/api/apps/v1" + "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/pkg/apis" @@ -348,7 +348,7 @@ func TestMakeReceiveAdapterWithServiceAccount(t *testing.T) { Name: "testname", Namespace: "testnamespace", Annotations: map[string]string{ - "metrics-resource-group": "test-resource-group", + "metrics-resource-group": "test-resource-group", duckv1beta1.ClusterNameAnnotation: testingmetadata.FakeClusterName, }, }, diff --git a/pkg/reconciler/intevents/reconciler.go b/pkg/reconciler/intevents/reconciler.go index 8dc0eb68c4..178e673063 100644 --- a/pkg/reconciler/intevents/reconciler.go +++ b/pkg/reconciler/intevents/reconciler.go @@ -30,7 +30,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" apierrs "k8s.io/apimachinery/pkg/api/errors" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/pkg/apis" "knative.dev/pkg/logging" pkgreconciler "knative.dev/pkg/reconciler" @@ -55,7 +55,7 @@ type PubSubBase struct { receiveAdapterName string // What type of receive adapter to use. - adapterType string + receiveAdapterType string } // ReconcilePubSub reconciles Topic / PullSubscription given a PubSubSpec. @@ -69,7 +69,7 @@ func (psb *PubSubBase) ReconcilePubSub(ctx context.Context, pubsubable duck.PubS return t, nil, err } - ps, err := psb.ReconcilePullSubscription(ctx, pubsubable, topic, resourceGroup, false) + ps, err := psb.ReconcilePullSubscription(ctx, pubsubable, topic, resourceGroup) if err != nil { return t, ps, err } @@ -128,7 +128,7 @@ func (psb *PubSubBase) reconcileTopic(ctx context.Context, pubsubable duck.PubSu return t, nil } -func (psb *PubSubBase) ReconcilePullSubscription(ctx context.Context, pubsubable duck.PubSubable, topic, resourceGroup string, isPushCompatible bool) (*inteventsv1beta1.PullSubscription, pkgreconciler.Event) { +func (psb *PubSubBase) ReconcilePullSubscription(ctx context.Context, pubsubable duck.PubSubable, topic, resourceGroup string) (*inteventsv1beta1.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") @@ -147,13 +147,11 @@ func (psb *PubSubBase) ReconcilePullSubscription(ctx context.Context, pubsubable Spec: spec, Owner: pubsubable, Topic: topic, - AdapterType: psb.adapterType, + AdapterType: psb.receiveAdapterType, Labels: resources.GetLabels(psb.receiveAdapterName, name), Annotations: resources.GetAnnotations(annotations, resourceGroup), } - if isPushCompatible { - args.Mode = inteventsv1beta1.ModePushCompatible - } + newPS := resources.MakePullSubscription(args) pullSubscriptions := psb.pubsubClient.InternalV1beta1().PullSubscriptions(namespace) From 85325c3051439e2b32d944d674408a05e36b87d1 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Thu, 18 Jun 2020 00:33:56 -0700 Subject: [PATCH 08/28] attempt to update tracing --- pkg/pubsub/adapter/adapter.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/pkg/pubsub/adapter/adapter.go b/pkg/pubsub/adapter/adapter.go index a9fa203179..0c03249ded 100644 --- a/pkg/pubsub/adapter/adapter.go +++ b/pkg/pubsub/adapter/adapter.go @@ -26,7 +26,6 @@ import ( "cloud.google.com/go/pubsub" "github.com/cloudevents/sdk-go/v2/binding" - ceclient "github.com/cloudevents/sdk-go/v2/client" cehttp "github.com/cloudevents/sdk-go/v2/protocol/http" "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "go.opencensus.io/trace" @@ -186,14 +185,9 @@ func (a *Adapter) receive(ctx context.Context, msg *pubsub.Message) { return } - // TODO check if this is OK // Update the tracing information to use the span returned by the transformer. - // ctx = trace.NewContext(ctx, trace.FromContext(transformedCTX)) - if span := trace.FromContext(ctx); span.IsRecordingEvents() { - span.Annotate(ceclient.EventTraceAttributes(event), - "Event reply", - ) - } + // TODO how to get the span returned by the transformer? + ctx = trace.NewContext(ctx, trace.FromContext(ctx)) reply = true } From cc27ea45239a88b40df6822bf4dc9061848c20d2 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Thu, 18 Jun 2020 11:20:27 -0700 Subject: [PATCH 09/28] adding pull converter to maintain pullsubscription functionality --- pkg/pubsub/adapter/converters/converters.go | 4 +- pkg/pubsub/adapter/converters/pubsub_pull.go | 64 ++++++++++ .../adapter/converters/pubsub_pull_test.go | 112 ++++++++++++++++++ pkg/pubsub/adapter/converters/pubsub_test.go | 2 +- .../resources/receive_adapter.go | 12 +- .../resources/receive_adapter_test.go | 8 +- 6 files changed, 195 insertions(+), 7 deletions(-) create mode 100644 pkg/pubsub/adapter/converters/pubsub_pull.go create mode 100644 pkg/pubsub/adapter/converters/pubsub_pull_test.go diff --git a/pkg/pubsub/adapter/converters/converters.go b/pkg/pubsub/adapter/converters/converters.go index 9116d8c229..41e31d6a9f 100644 --- a/pkg/pubsub/adapter/converters/converters.go +++ b/pkg/pubsub/adapter/converters/converters.go @@ -38,8 +38,6 @@ const ( Structured ModeType = "structured" // Push mode emulates Pub/Sub push encoding. Push ModeType = "push" - // DefaultSendMode is the default choice. - DefaultSendMode = Binary ) type ConverterType string @@ -51,6 +49,7 @@ const ( CloudAuditLogs ConverterType = "auditlogs" CloudScheduler ConverterType = "scheduler" CloudBuild ConverterType = "build" + PubSubPull ConverterType = "pubsub_pull" ) type converterFn func(context.Context, *pubsub.Message) (*cev2.Event, error) @@ -77,6 +76,7 @@ func NewPubSubConverter() Converter { CloudStorage: convertCloudStorage, CloudScheduler: convertCloudScheduler, CloudBuild: convertCloudBuild, + PubSubPull: convertPubSubPull, }, } } diff --git a/pkg/pubsub/adapter/converters/pubsub_pull.go b/pkg/pubsub/adapter/converters/pubsub_pull.go new file mode 100644 index 0000000000..2bd552d265 --- /dev/null +++ b/pkg/pubsub/adapter/converters/pubsub_pull.go @@ -0,0 +1,64 @@ +/* +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 converters + +import ( + "cloud.google.com/go/pubsub" + "context" + "fmt" + cev2 "github.com/cloudevents/sdk-go/v2" + . "github.com/cloudevents/sdk-go/v2/event" + "github.com/google/knative-gcp/pkg/apis/events/v1beta1" + . "github.com/google/knative-gcp/pkg/pubsub/adapter/context" +) + +func convertPubSubPull(ctx context.Context, msg *pubsub.Message) (*cev2.Event, error) { + event := cev2.NewEvent(cev2.VersionV1) + event.SetID(msg.ID) + event.SetTime(msg.PublishTime) + + project, err := GetProjectKey(ctx) + if err != nil { + return nil, err + } + topic, err := GetTopicKey(ctx) + if err != nil { + return nil, err + } + + event.SetSource(v1beta1.CloudPubSubSourceEventSource(project, topic)) + event.SetType(v1beta1.CloudPubSubSourcePublish) + + // We promote attributes to extensions. If there is at least one attribute that cannot be promoted, we fail. + if msg.Attributes != nil && len(msg.Attributes) > 0 { + for k, v := range msg.Attributes { + // CloudEvents v1.0 attributes MUST consist of lower-case letters ('a' to 'z') or digits ('0' to '9') as per + // the spec. It's not even possible for a conformant transport to allow non-base36 characters. + // Note `SetExtension` will make it lowercase so only `IsAlphaNumeric` needs to be checked here. + if !IsAlphaNumeric(k) { + return nil, fmt.Errorf("cannot convert attribute %q to extension", k) + } + event.SetExtension(k, v) + } + } + // We do not know the content type and we do not want to inspect the payload, + // thus we set this generic one. + if err := event.SetData("application/octet-stream", msg.Data); err != nil { + return nil, err + } + return &event, nil +} diff --git a/pkg/pubsub/adapter/converters/pubsub_pull_test.go b/pkg/pubsub/adapter/converters/pubsub_pull_test.go new file mode 100644 index 0000000000..0ae23656f0 --- /dev/null +++ b/pkg/pubsub/adapter/converters/pubsub_pull_test.go @@ -0,0 +1,112 @@ +/* +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 converters + +import ( + "context" + "github.com/cloudevents/sdk-go" + "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" + "testing" + + "cloud.google.com/go/pubsub" + cev2 "github.com/cloudevents/sdk-go/v2" + "github.com/google/go-cmp/cmp" + . "github.com/google/knative-gcp/pkg/pubsub/adapter/context" +) + +func TestConvertPubSubPull(t *testing.T) { + + tests := []struct { + name string + message *pubsub.Message + wantEventFn func() *cev2.Event + wantErr bool + }{{ + name: "valid attributes", + message: &pubsub.Message{ + ID: "id", + Data: []byte("test data"), + Attributes: map[string]string{ + "attribute1": "value1", + "attribute2": "value2", + }, + }, + wantEventFn: func() *cev2.Event { + return pubSubPull(map[string]string{ + "attribute1": "value1", + "attribute2": "value2", + }) + }, + }, { + name: "upper case attributes", + message: &pubsub.Message{ + ID: "id", + Data: []byte("test data"), + Attributes: map[string]string{ + "AttriBUte1": "value1", + "AttrIbuTe2": "value2", + }, + }, + wantEventFn: func() *cev2.Event { + return pubSubPull(map[string]string{ + "attribute1": "value1", + "attribute2": "value2", + }) + }, + }, { + name: "failing with invalid attributes", + message: &pubsub.Message{ + Data: []byte("test data"), + Attributes: map[string]string{ + "attribute1": "value1", + "Invalid-Attrib#$^": "value2", + }, + }, + wantErr: true, + }} + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ctx := WithProjectKey(context.Background(), "testproject") + ctx = WithTopicKey(ctx, "testtopic") + ctx = WithSubscriptionKey(ctx, "testsubscription") + + gotEvent, err := NewPubSubConverter().Convert(ctx, test.message, PubSubPull) + if err != nil { + if !test.wantErr { + t.Errorf("converters.convertPubsubPull got error %v want error=%v", err, test.wantErr) + } + } else { + if diff := cmp.Diff(test.wantEventFn(), gotEvent); diff != "" { + t.Errorf("converters.convertPubsubPull got unexpeceted cloudevents.Event (-want +got) %s", diff) + } + } + }) + } +} + +func pubSubPull(extensions map[string]string) *cev2.Event { + e := cev2.NewEvent(cloudevents.VersionV1) + e.SetID("id") + e.SetSource(v1alpha1.CloudPubSubSourceEventSource("testproject", "testtopic")) + e.SetType(v1alpha1.CloudPubSubSourcePublish) + e.SetData("application/octet-stream", []byte("test data")) + for k, v := range extensions { + e.SetExtension(k, v) + } + return &e +} diff --git a/pkg/pubsub/adapter/converters/pubsub_test.go b/pkg/pubsub/adapter/converters/pubsub_test.go index 5943a815e3..069dfdabc1 100644 --- a/pkg/pubsub/adapter/converters/pubsub_test.go +++ b/pkg/pubsub/adapter/converters/pubsub_test.go @@ -37,7 +37,7 @@ func TestConvertCloudPubSub(t *testing.T) { wantEventFn func() *cev2.Event wantErr bool }{{ - name: "non valid alphanumeric attribute", + name: "non alphanumeric attribute", message: &pubsub.Message{ ID: "id", Data: []byte("\"test data\""), // Data passed in quotes for it to be marshalled properly diff --git a/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter.go b/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter.go index 6cf144d3e5..872fc4dde8 100644 --- a/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter.go +++ b/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter.go @@ -26,6 +26,7 @@ import ( "knative.dev/pkg/kmeta" "knative.dev/pkg/logging" + "github.com/google/knative-gcp/pkg/apis/intevents" "github.com/google/knative-gcp/pkg/apis/intevents/v1beta1" "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "github.com/google/knative-gcp/pkg/utils" @@ -94,6 +95,15 @@ func makeReceiveAdapterPodSpec(ctx context.Context, args *ReceiveAdapterArgs) *c transformerURI = args.TransformerURI.String() } + adapterType := args.PullSubscription.Spec.AdapterType + // If the PullSubscription has no Channel nor Source label, means that users created a PullSubscription manually. + // Then we set the adapter type to be PubSubPull. + _, isFromSource := args.PullSubscription.Labels[intevents.SourceLabelKey] + _, isFromChannel := args.PullSubscription.Labels[intevents.ChannelLabelKey] + if !isFromSource && !isFromChannel { + adapterType = string(converters.PubSubPull) + } + receiveAdapterContainer := corev1.Container{ Name: "receive-adapter", Image: args.Image, @@ -114,7 +124,7 @@ func makeReceiveAdapterPodSpec(ctx context.Context, args *ReceiveAdapterArgs) *c Value: transformerURI, }, { Name: "ADAPTER_TYPE", - Value: args.PullSubscription.Spec.AdapterType, + Value: adapterType, }, { Name: "SEND_MODE", Value: string(mode), diff --git a/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go b/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go index f5749750cc..273ec2bbf9 100644 --- a/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go +++ b/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go @@ -25,6 +25,7 @@ import ( duckv1beta1 "github.com/google/knative-gcp/pkg/apis/duck/v1beta1" "github.com/google/knative-gcp/pkg/apis/intevents/v1beta1" testingmetadata "github.com/google/knative-gcp/pkg/gclient/metadata/testing" + "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -121,6 +122,7 @@ func TestMakeMinimumReceiveAdapter(t *testing.T) { Name: "TRANSFORMER_URI", }, { Name: "ADAPTER_TYPE", + Value: string(converters.PubSubPull), }, { Name: "SEND_MODE", Value: "binary", @@ -205,7 +207,7 @@ func TestMakeFullReceiveAdapter(t *testing.T) { }, }, Topic: "topic", - AdapterType: "adapter-type", + AdapterType: string(converters.PubSubPull), }, } @@ -279,7 +281,7 @@ func TestMakeFullReceiveAdapter(t *testing.T) { Value: "http://transformer-uri", }, { Name: "ADAPTER_TYPE", - Value: "adapter-type", + Value: string(converters.PubSubPull), }, { Name: "SEND_MODE", Value: "binary", @@ -442,7 +444,7 @@ func TestMakeReceiveAdapterWithServiceAccount(t *testing.T) { Value: "http://transformer-uri", }, { Name: "ADAPTER_TYPE", - Value: "adapter-type", + Value: string(converters.PubSubPull), }, { Name: "SEND_MODE", Value: "binary", From a55ab95c25cf364dcc1bafcb6700fc684eddece5 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Thu, 18 Jun 2020 15:00:56 -0700 Subject: [PATCH 10/28] another try at tracing --- cmd/broker/fanout/main.go | 3 +- cmd/broker/fanout/wire.go | 3 +- cmd/broker/fanout/wire_gen.go | 5 ++- cmd/broker/retry/main.go | 3 +- cmd/broker/retry/wire.go | 3 +- cmd/broker/retry/wire_gen.go | 5 ++- cmd/pubsub/receive_adapter/main.go | 2 +- cmd/pubsub/receive_adapter/wire.go | 2 +- cmd/pubsub/receive_adapter/wire_gen.go | 4 +- pkg/broker/handler/providers.go | 13 ++----- pkg/pubsub/adapter/adapter.go | 52 ++++++++++++++++++++------ pkg/tracing/attributes.go | 10 ++++- 12 files changed, 70 insertions(+), 35 deletions(-) diff --git a/cmd/broker/fanout/main.go b/cmd/broker/fanout/main.go index 5432f260d4..d0c160fdca 100644 --- a/cmd/broker/fanout/main.go +++ b/cmd/broker/fanout/main.go @@ -28,6 +28,7 @@ import ( "github.com/google/knative-gcp/pkg/metrics" "github.com/google/knative-gcp/pkg/utils" "github.com/google/knative-gcp/pkg/utils/appcredentials" + "github.com/google/knative-gcp/pkg/utils/clients" "github.com/google/knative-gcp/pkg/utils/mainhelper" "go.uber.org/zap" @@ -81,7 +82,7 @@ func main() { syncSignal := poolSyncSignal(ctx, targetsUpdateCh) syncPool, err := InitializeSyncPool( ctx, - handler.ProjectID(projectID), + clients.ProjectID(projectID), metrics.PodName(env.PodName), metrics.ContainerName(component), []volume.Option{ diff --git a/cmd/broker/fanout/wire.go b/cmd/broker/fanout/wire.go index 08f8fb819e..9fd978b39a 100644 --- a/cmd/broker/fanout/wire.go +++ b/cmd/broker/fanout/wire.go @@ -24,6 +24,7 @@ import ( "github.com/google/knative-gcp/pkg/broker/config/volume" "github.com/google/knative-gcp/pkg/broker/handler" "github.com/google/knative-gcp/pkg/metrics" + "github.com/google/knative-gcp/pkg/utils/clients" "github.com/google/wire" ) @@ -31,7 +32,7 @@ import ( // retry pool's pubsub client and uses targetsVolumeOpts to initialize the targets volume watcher. func InitializeSyncPool( ctx context.Context, - projectID handler.ProjectID, + projectID clients.ProjectID, podName metrics.PodName, containerName metrics.ContainerName, targetsVolumeOpts []volume.Option, diff --git a/cmd/broker/fanout/wire_gen.go b/cmd/broker/fanout/wire_gen.go index 19272d22a3..1b991a5fb7 100644 --- a/cmd/broker/fanout/wire_gen.go +++ b/cmd/broker/fanout/wire_gen.go @@ -10,16 +10,17 @@ import ( "github.com/google/knative-gcp/pkg/broker/config/volume" "github.com/google/knative-gcp/pkg/broker/handler" "github.com/google/knative-gcp/pkg/metrics" + "github.com/google/knative-gcp/pkg/utils/clients" ) // Injectors from wire.go: -func InitializeSyncPool(ctx context.Context, projectID handler.ProjectID, podName metrics.PodName, containerName metrics.ContainerName, targetsVolumeOpts []volume.Option, opts ...handler.Option) (*handler.FanoutPool, error) { +func InitializeSyncPool(ctx context.Context, projectID clients.ProjectID, podName metrics.PodName, containerName metrics.ContainerName, targetsVolumeOpts []volume.Option, opts ...handler.Option) (*handler.FanoutPool, error) { readonlyTargets, err := volume.NewTargetsFromFile(targetsVolumeOpts...) if err != nil { return nil, err } - client, err := handler.NewPubsubClient(ctx, projectID) + client, err := clients.NewPubsubClient(ctx, projectID) if err != nil { return nil, err } diff --git a/cmd/broker/retry/main.go b/cmd/broker/retry/main.go index 21e6820a8e..a5da28998b 100644 --- a/cmd/broker/retry/main.go +++ b/cmd/broker/retry/main.go @@ -30,6 +30,7 @@ import ( "github.com/google/knative-gcp/pkg/metrics" "github.com/google/knative-gcp/pkg/utils" "github.com/google/knative-gcp/pkg/utils/appcredentials" + "github.com/google/knative-gcp/pkg/utils/clients" "github.com/google/knative-gcp/pkg/utils/mainhelper" ) @@ -89,7 +90,7 @@ func main() { syncSignal := poolSyncSignal(ctx, targetsUpdateCh) syncPool, err := InitializeSyncPool( ctx, - handler.ProjectID(projectID), + clients.ProjectID(projectID), metrics.PodName(env.PodName), metrics.ContainerName(component), []volume.Option{ diff --git a/cmd/broker/retry/wire.go b/cmd/broker/retry/wire.go index 6cf68e6c41..9574112f41 100644 --- a/cmd/broker/retry/wire.go +++ b/cmd/broker/retry/wire.go @@ -24,6 +24,7 @@ import ( "github.com/google/knative-gcp/pkg/broker/config/volume" "github.com/google/knative-gcp/pkg/broker/handler" "github.com/google/knative-gcp/pkg/metrics" + "github.com/google/knative-gcp/pkg/utils/clients" "github.com/google/wire" ) @@ -31,7 +32,7 @@ import ( // retry pool's pubsub client and uses targetsVolumeOpts to initialize the targets volume watcher. func InitializeSyncPool( ctx context.Context, - projectID handler.ProjectID, + projectID clients.ProjectID, podName metrics.PodName, containerName metrics.ContainerName, targetsVolumeOpts []volume.Option, diff --git a/cmd/broker/retry/wire_gen.go b/cmd/broker/retry/wire_gen.go index 040fb55b16..43145d0bb6 100644 --- a/cmd/broker/retry/wire_gen.go +++ b/cmd/broker/retry/wire_gen.go @@ -10,16 +10,17 @@ import ( "github.com/google/knative-gcp/pkg/broker/config/volume" "github.com/google/knative-gcp/pkg/broker/handler" "github.com/google/knative-gcp/pkg/metrics" + "github.com/google/knative-gcp/pkg/utils/clients" ) // Injectors from wire.go: -func InitializeSyncPool(ctx context.Context, projectID handler.ProjectID, podName metrics.PodName, containerName metrics.ContainerName, targetsVolumeOpts []volume.Option, opts ...handler.Option) (*handler.RetryPool, error) { +func InitializeSyncPool(ctx context.Context, projectID clients.ProjectID, podName metrics.PodName, containerName metrics.ContainerName, targetsVolumeOpts []volume.Option, opts ...handler.Option) (*handler.RetryPool, error) { readonlyTargets, err := volume.NewTargetsFromFile(targetsVolumeOpts...) if err != nil { return nil, err } - client, err := handler.NewPubsubClient(ctx, projectID) + client, err := clients.NewPubsubClient(ctx, projectID) if err != nil { return nil, err } diff --git a/cmd/pubsub/receive_adapter/main.go b/cmd/pubsub/receive_adapter/main.go index f242874975..2838101114 100644 --- a/cmd/pubsub/receive_adapter/main.go +++ b/cmd/pubsub/receive_adapter/main.go @@ -173,8 +173,8 @@ func main() { clients.ProjectID(projectID), SubscriptionID(env.Subscription), clients.MaxConnsPerHost(maxConnectionsPerHost), - Name(env.Name), Namespace(env.Namespace), + Name(env.Name), ResourceGroup(env.ResourceGroup), converters.ConverterType(env.AdapterType), SinkURI(env.Sink), diff --git a/cmd/pubsub/receive_adapter/wire.go b/cmd/pubsub/receive_adapter/wire.go index 05f4795f95..d653de5120 100644 --- a/cmd/pubsub/receive_adapter/wire.go +++ b/cmd/pubsub/receive_adapter/wire.go @@ -33,8 +33,8 @@ func InitializeAdapter( projectID clients.ProjectID, subscription adapter.SubscriptionID, maxConnsPerHost clients.MaxConnsPerHost, - name adapter.Name, namespace adapter.Namespace, + name adapter.Name, resourceGroup adapter.ResourceGroup, converterType converters.ConverterType, sinkURI adapter.SinkURI, diff --git a/cmd/pubsub/receive_adapter/wire_gen.go b/cmd/pubsub/receive_adapter/wire_gen.go index 8ffb484afa..78f9005390 100644 --- a/cmd/pubsub/receive_adapter/wire_gen.go +++ b/cmd/pubsub/receive_adapter/wire_gen.go @@ -14,7 +14,7 @@ import ( // Injectors from wire.go: -func InitializeAdapter(ctx context.Context, projectID clients.ProjectID, subscription adapter.SubscriptionID, maxConnsPerHost clients.MaxConnsPerHost, name adapter.Name, namespace adapter.Namespace, resourceGroup adapter.ResourceGroup, converterType converters.ConverterType, sinkURI adapter.SinkURI, transformerURI adapter.TransformerURI, extensions map[string]string) (*adapter.Adapter, error) { +func InitializeAdapter(ctx context.Context, projectID clients.ProjectID, subscription adapter.SubscriptionID, maxConnsPerHost clients.MaxConnsPerHost, namespace adapter.Namespace, name adapter.Name, resourceGroup adapter.ResourceGroup, converterType converters.ConverterType, sinkURI adapter.SinkURI, transformerURI adapter.TransformerURI, extensions map[string]string) (*adapter.Adapter, error) { client, err := clients.NewPubsubClient(ctx, projectID) if err != nil { return nil, err @@ -26,6 +26,6 @@ func InitializeAdapter(ctx context.Context, projectID clients.ProjectID, subscri if err != nil { return nil, err } - adapterAdapter := adapter.NewAdapter(ctx, pubsubSubscription, httpClient, converter, statsReporter, sinkURI, transformerURI, converterType, extensions) + adapterAdapter := adapter.NewAdapter(ctx, pubsubSubscription, httpClient, converter, statsReporter, namespace, name, sinkURI, transformerURI, converterType, extensions) return adapterAdapter, nil } diff --git a/pkg/broker/handler/providers.go b/pkg/broker/handler/providers.go index 65f2bed7b6..4b425ae8f9 100644 --- a/pkg/broker/handler/providers.go +++ b/pkg/broker/handler/providers.go @@ -24,6 +24,7 @@ import ( "cloud.google.com/go/pubsub" cepubsub "github.com/cloudevents/sdk-go/protocol/pubsub/v2" ceclient "github.com/cloudevents/sdk-go/v2/client" + "github.com/google/knative-gcp/pkg/utils/clients" "github.com/google/wire" "go.opencensus.io/plugin/ochttp" "go.opencensus.io/plugin/ochttp/propagation/tracecontext" @@ -54,22 +55,14 @@ var ( ProviderSet = wire.NewSet( NewFanoutPool, NewRetryPool, - NewPubsubClient, + clients.NewPubsubClient, NewRetryClient, wire.Value(DefaultHTTPClient), wire.Value(DefaultCEClientOpts), ) ) -type ( - ProjectID string - RetryClient ceclient.Client -) - -// NewPubsubClient provides a pubsub client for the supplied project ID. -func NewPubsubClient(ctx context.Context, projectID ProjectID) (*pubsub.Client, error) { - return pubsub.NewClient(ctx, string(projectID)) -} +type RetryClient ceclient.Client // NewRetryClient provides a retry CE client from a PubSub client and list of CE client options. func NewRetryClient(ctx context.Context, client *pubsub.Client, opts ...ceclient.Option) (RetryClient, error) { diff --git a/pkg/pubsub/adapter/adapter.go b/pkg/pubsub/adapter/adapter.go index 0c03249ded..c40e772514 100644 --- a/pkg/pubsub/adapter/adapter.go +++ b/pkg/pubsub/adapter/adapter.go @@ -25,11 +25,16 @@ import ( "go.uber.org/zap" "cloud.google.com/go/pubsub" + cev2 "github.com/cloudevents/sdk-go/v2" "github.com/cloudevents/sdk-go/v2/binding" + "github.com/cloudevents/sdk-go/v2/extensions" cehttp "github.com/cloudevents/sdk-go/v2/protocol/http" "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" + "github.com/google/knative-gcp/pkg/tracing" "go.opencensus.io/trace" + "k8s.io/apimachinery/pkg/types" "knative.dev/eventing/pkg/logging" + kntracing "knative.dev/eventing/pkg/tracing" ) // Adapter implements the Pub/Sub adapter to deliver Pub/Sub messages from a @@ -64,6 +69,9 @@ type Adapter struct { cancel context.CancelFunc logger *zap.Logger + + // name of the resource this receive adapter belong to. + namespacedResourceName types.NamespacedName } // NewAdapter creates a new adapter. @@ -73,20 +81,23 @@ func NewAdapter( outbound *nethttp.Client, converter converters.Converter, reporter StatsReporter, + namespace Namespace, + name Name, sinkURI SinkURI, transformerURI TransformerURI, converterType converters.ConverterType, extensions map[string]string) *Adapter { return &Adapter{ - subscription: subscription, - outbound: outbound, - converter: converter, - reporter: reporter, - sinkURI: string(sinkURI), - transformerURI: string(transformerURI), - converterType: converterType, - extensions: extensions, - logger: logging.FromContext(ctx), + subscription: subscription, + outbound: outbound, + converter: converter, + reporter: reporter, + sinkURI: string(sinkURI), + transformerURI: string(transformerURI), + namespacedResourceName: types.NamespacedName{Name: string(name), Namespace: string(namespace)}, + converterType: converterType, + extensions: extensions, + logger: logging.FromContext(ctx), } } @@ -186,9 +197,9 @@ func (a *Adapter) receive(ctx context.Context, msg *pubsub.Message) { } // Update the tracing information to use the span returned by the transformer. - // TODO how to get the span returned by the transformer? - ctx = trace.NewContext(ctx, trace.FromContext(ctx)) - + var span *trace.Span + ctx, span = a.startSpan(ctx, event) + defer span.End() reply = true } @@ -233,3 +244,20 @@ func (a *Adapter) sendMsg(ctx context.Context, address string, msg binding.Messa } return a.outbound.Do(req) } + +func (a *Adapter) startSpan(ctx context.Context, event *cev2.Event) (context.Context, *trace.Span) { + var span *trace.Span + if dt, ok := extensions.GetDistributedTracingExtension(*event); ok { + ctx, span = dt.StartChildSpan(ctx, tracing.ChannelMessagingDestination(a.namespacedResourceName)) + } else { + ctx, span = trace.StartSpan(ctx, tracing.ChannelMessagingDestination(a.namespacedResourceName)) + } + if span.IsRecordingEvents() { + span.AddAttributes( + kntracing.MessagingSystemAttribute, + tracing.PubSubProtocolAttribute, + kntracing.MessagingMessageIDAttribute(event.ID()), + ) + } + return ctx, span +} diff --git a/pkg/tracing/attributes.go b/pkg/tracing/attributes.go index 78c742f12b..64cc569250 100644 --- a/pkg/tracing/attributes.go +++ b/pkg/tracing/attributes.go @@ -16,7 +16,11 @@ limitations under the License. package tracing -import "knative.dev/eventing/pkg/tracing" +import ( + "fmt" + "k8s.io/apimachinery/pkg/types" + "knative.dev/eventing/pkg/tracing" +) const ( PubSubProtocol = "Pub/Sub" @@ -25,3 +29,7 @@ const ( var ( PubSubProtocolAttribute = tracing.MessagingProtocolAttribute(PubSubProtocol) ) + +func ChannelMessagingDestination(c types.NamespacedName) string { + return fmt.Sprintf("channel:%s.%s", c.Name, c.Namespace) +} From 9bd1f1759161eb696a8d52af8e583bf7e567dc4d Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Mon, 22 Jun 2020 17:32:28 -0700 Subject: [PATCH 11/28] updates after code review --- cmd/pubsub/publisher/main.go | 2 +- cmd/pubsub/receive_adapter/main.go | 23 ++-- cmd/pubsub/receive_adapter/wire.go | 11 +- cmd/pubsub/receive_adapter/wire_gen.go | 6 +- pkg/pubsub/adapter/adapter.go | 136 ++++++++++++-------- pkg/pubsub/adapter/converters/converters.go | 1 + pkg/pubsub/adapter/providers.go | 1 + pkg/tracing/attributes.go | 6 +- 8 files changed, 107 insertions(+), 79 deletions(-) diff --git a/cmd/pubsub/publisher/main.go b/cmd/pubsub/publisher/main.go index 561c125b28..63c3d1f8a2 100644 --- a/cmd/pubsub/publisher/main.go +++ b/cmd/pubsub/publisher/main.go @@ -102,6 +102,6 @@ func main() { logger.Info("Starting publisher", zap.Any("publisher", publisher)) if err := publisher.Start(ctx); err != nil { - logger.Fatal("Failed to start publisher", zap.Error(err)) + logger.Error("Publisher has stopped with error", zap.String("Project ID", projectID), zap.String("Topic ID", topicID), zap.Error(err)) } } diff --git a/cmd/pubsub/receive_adapter/main.go b/cmd/pubsub/receive_adapter/main.go index 2838101114..1c5d2e72c3 100644 --- a/cmd/pubsub/receive_adapter/main.go +++ b/cmd/pubsub/receive_adapter/main.go @@ -27,7 +27,6 @@ import ( metadataClient "github.com/google/knative-gcp/pkg/gclient/metadata" . "github.com/google/knative-gcp/pkg/pubsub/adapter" - "github.com/google/knative-gcp/pkg/pubsub/adapter/context" "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" tracingconfig "github.com/google/knative-gcp/pkg/tracing" "github.com/google/knative-gcp/pkg/utils" @@ -162,24 +161,24 @@ func main() { logger.Error("Failed to convert base64 extensions to map: %v", zap.Error(err)) } - ctx = context.WithProjectKey(ctx, projectID) - ctx = context.WithTopicKey(ctx, env.Topic) - ctx = context.WithSubscriptionKey(ctx, env.Subscription) - logger.Info("Initializing adapter", zap.String("projectID", projectID), zap.String("topicID", env.Topic), zap.String("subscriptionID", env.Subscription)) - adapter, err := InitializeAdapter( - ctx, + args := &AdapterArgs{ + TopicID: env.Topic, + ConverterType: converters.ConverterType(env.AdapterType), + SinkURI: env.Sink, + TransformerURI: env.Transformer, + Extensions: extensions, + } + + adapter, err := InitializeAdapter(ctx, + clients.MaxConnsPerHost(maxConnectionsPerHost), clients.ProjectID(projectID), SubscriptionID(env.Subscription), - clients.MaxConnsPerHost(maxConnectionsPerHost), Namespace(env.Namespace), Name(env.Name), ResourceGroup(env.ResourceGroup), - converters.ConverterType(env.AdapterType), - SinkURI(env.Sink), - TransformerURI(env.Transformer), - extensions) + args) if err != nil { logger.Fatal("Unable to create adapter", zap.Error(err)) diff --git a/cmd/pubsub/receive_adapter/wire.go b/cmd/pubsub/receive_adapter/wire.go index d653de5120..b7b83479db 100644 --- a/cmd/pubsub/receive_adapter/wire.go +++ b/cmd/pubsub/receive_adapter/wire.go @@ -22,7 +22,6 @@ import ( "context" "github.com/google/knative-gcp/pkg/pubsub/adapter" - "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "github.com/google/knative-gcp/pkg/utils/clients" "github.com/google/wire" @@ -30,17 +29,13 @@ import ( func InitializeAdapter( ctx context.Context, - projectID clients.ProjectID, - subscription adapter.SubscriptionID, maxConnsPerHost clients.MaxConnsPerHost, + projectID clients.ProjectID, + subscriptionID adapter.SubscriptionID, namespace adapter.Namespace, name adapter.Name, resourceGroup adapter.ResourceGroup, - converterType converters.ConverterType, - sinkURI adapter.SinkURI, - transformerURI adapter.TransformerURI, - extensions map[string]string, -) (*adapter.Adapter, error) { + args *adapter.AdapterArgs) (*adapter.Adapter, error) { panic(wire.Build( adapter.AdapterSet, )) diff --git a/cmd/pubsub/receive_adapter/wire_gen.go b/cmd/pubsub/receive_adapter/wire_gen.go index 78f9005390..e78f6005c0 100644 --- a/cmd/pubsub/receive_adapter/wire_gen.go +++ b/cmd/pubsub/receive_adapter/wire_gen.go @@ -14,18 +14,18 @@ import ( // Injectors from wire.go: -func InitializeAdapter(ctx context.Context, projectID clients.ProjectID, subscription adapter.SubscriptionID, maxConnsPerHost clients.MaxConnsPerHost, namespace adapter.Namespace, name adapter.Name, resourceGroup adapter.ResourceGroup, converterType converters.ConverterType, sinkURI adapter.SinkURI, transformerURI adapter.TransformerURI, extensions map[string]string) (*adapter.Adapter, error) { +func InitializeAdapter(ctx context.Context, maxConnsPerHost clients.MaxConnsPerHost, projectID clients.ProjectID, subscriptionID adapter.SubscriptionID, namespace adapter.Namespace, name adapter.Name, resourceGroup adapter.ResourceGroup, args *adapter.AdapterArgs) (*adapter.Adapter, error) { client, err := clients.NewPubsubClient(ctx, projectID) if err != nil { return nil, err } - pubsubSubscription := adapter.NewPubSubSubscription(ctx, client, subscription) + subscription := adapter.NewPubSubSubscription(ctx, client, subscriptionID) httpClient := clients.NewHTTPClient(ctx, maxConnsPerHost) converter := converters.NewPubSubConverter() statsReporter, err := adapter.NewStatsReporter(name, namespace, resourceGroup) if err != nil { return nil, err } - adapterAdapter := adapter.NewAdapter(ctx, pubsubSubscription, httpClient, converter, statsReporter, namespace, name, sinkURI, transformerURI, converterType, extensions) + adapterAdapter := adapter.NewAdapter(ctx, projectID, namespace, name, resourceGroup, subscription, httpClient, converter, statsReporter, args) return adapterAdapter, nil } diff --git a/pkg/pubsub/adapter/adapter.go b/pkg/pubsub/adapter/adapter.go index c40e772514..96608ab293 100644 --- a/pkg/pubsub/adapter/adapter.go +++ b/pkg/pubsub/adapter/adapter.go @@ -19,6 +19,7 @@ package adapter import ( "context" "errors" + "github.com/google/knative-gcp/pkg/apis/messaging" nethttp "net/http" "time" @@ -29,14 +30,35 @@ import ( "github.com/cloudevents/sdk-go/v2/binding" "github.com/cloudevents/sdk-go/v2/extensions" cehttp "github.com/cloudevents/sdk-go/v2/protocol/http" + . "github.com/google/knative-gcp/pkg/pubsub/adapter/context" "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "github.com/google/knative-gcp/pkg/tracing" + "github.com/google/knative-gcp/pkg/utils/clients" "go.opencensus.io/trace" "k8s.io/apimachinery/pkg/types" "knative.dev/eventing/pkg/logging" kntracing "knative.dev/eventing/pkg/tracing" ) +// AdapterArgs has a bundle of arguments needed to create an Adapter. +type AdapterArgs struct { + // TopicID is the id of the Pub/Sub topic. + TopicID string + + // SinkURI is the URI where to sink events to. + SinkURI string + + // TransformerURI is the URI for the transformer. + // Used for channels. + TransformerURI string + + // Extensions is the converted ExtensionsBased64 value. + Extensions map[string]string + + // ConverterType use to select which converter to use. + ConverterType converters.ConverterType +} + // Adapter implements the Pub/Sub adapter to deliver Pub/Sub messages from a // pre-existing topic/subscription to a Sink. type Adapter struct { @@ -46,58 +68,52 @@ type Adapter struct { // outbound is the client used to send events to. outbound *nethttp.Client - // sinkURI is the URI where to sink events to. - sinkURI string - - // transformerURI is the URI for the transformer. - // Used for channels. - transformerURI string - - // extensions is the converted ExtensionsBased64 value. - extensions map[string]string - - // converterType use to select which converter to use. - converterType converters.ConverterType - // reporter reports metrics to the configured backend. reporter StatsReporter // converter used to convert pubsub messages to CE. converter converters.Converter + // projectID is the id of the GCP project. + projectID string + + // namespacedName is the namespaced name of the resource this receive adapter belong to. + namespacedName types.NamespacedName + + // resourceGroup is the resource group name this receive adapter belong to. + resourceGroup string + + // args holds a set of arguments used to configure the Adapter. + args *AdapterArgs + // cancel is function to stop pulling messages. cancel context.CancelFunc logger *zap.Logger - - // name of the resource this receive adapter belong to. - namespacedResourceName types.NamespacedName } // NewAdapter creates a new adapter. func NewAdapter( ctx context.Context, + projectID clients.ProjectID, + namespace Namespace, + name Name, + resourceGroup ResourceGroup, subscription *pubsub.Subscription, outbound *nethttp.Client, converter converters.Converter, reporter StatsReporter, - namespace Namespace, - name Name, - sinkURI SinkURI, - transformerURI TransformerURI, - converterType converters.ConverterType, - extensions map[string]string) *Adapter { + args *AdapterArgs) *Adapter { return &Adapter{ - subscription: subscription, - outbound: outbound, - converter: converter, - reporter: reporter, - sinkURI: string(sinkURI), - transformerURI: string(transformerURI), - namespacedResourceName: types.NamespacedName{Name: string(name), Namespace: string(namespace)}, - converterType: converterType, - extensions: extensions, - logger: logging.FromContext(ctx), + subscription: subscription, + projectID: string(projectID), + namespacedName: types.NamespacedName{Namespace: string(namespace), Name: string(name)}, + resourceGroup: string(resourceGroup), + outbound: outbound, + converter: converter, + reporter: reporter, + args: args, + logger: logging.FromContext(ctx), } } @@ -105,6 +121,11 @@ func (a *Adapter) Start(ctx context.Context) error { ctx, a.cancel = context.WithCancel(ctx) defer a.cancel() + // Augment context so that we can use it to create CE attributes. + ctx = WithProjectKey(ctx, a.projectID) + ctx = WithTopicKey(ctx, a.args.TopicID) + ctx = WithSubscriptionKey(ctx, a.subscription.ID()) + errCh := make(chan error, 1) go func() { errCh <- a.subscription.Receive(ctx, a.receive) @@ -137,14 +158,17 @@ func (a *Adapter) Stop() { // TODO refactor this method. As our RA code is used both for Sources and our Channel, it also supports replies // (in the case of Channels) and the logic is more convoluted. func (a *Adapter) receive(ctx context.Context, msg *pubsub.Message) { - event, err := a.converter.Convert(ctx, msg, a.converterType) + event, err := a.converter.Convert(ctx, msg, a.args.ConverterType) if err != nil { a.logger.Debug("Failed to convert received message to an event, check the msg format: %w", zap.Error(err)) - // Ack the message so it won't be retried + // Ack the message so it won't be retried, we consider all errors to be non-retryable. msg.Ack() return } + ctx, span := a.startSpan(ctx, event) + defer span.End() + args := &ReportArgs{ EventType: event.Type(), EventSource: event.Source(), @@ -157,10 +181,10 @@ func (a *Adapter) receive(ctx context.Context, msg *pubsub.Message) { // Note that currently this path of the code will be executed when using the receive adapter as part of the underlying Channel, // in case both subscriber and reply are set. The transformer would act as the subscriber and the sink will be where // we will send the reply. - if a.transformerURI != "" { - resp, err := a.sendMsg(ctx, a.transformerURI, (*binding.EventMessage)(event)) + if a.args.TransformerURI != "" { + resp, err := a.sendMsg(ctx, a.args.TransformerURI, (*binding.EventMessage)(event)) if err != nil { - a.logger.Error("Failed to send message to transformer", zap.String("address", a.transformerURI), zap.Error(err)) + a.logger.Error("Failed to send message to transformer", zap.String("address", a.args.TransformerURI), zap.Error(err)) msg.Nack() return } @@ -192,14 +216,10 @@ func (a *Adapter) receive(ctx context.Context, msg *pubsub.Message) { if err != nil { a.logger.Error("Failed to convert response message to event", zap.Any("response", respMsg), zap.Error(err)) - msg.Ack() + msg.Nack() return } - // Update the tracing information to use the span returned by the transformer. - var span *trace.Span - ctx, span = a.startSpan(ctx, event) - defer span.End() reply = true } @@ -207,30 +227,32 @@ func (a *Adapter) receive(ctx context.Context, msg *pubsub.Message) { if !reply { // Apply CloudEvent override extensions to the outbound event. // This code will be mainly executed by Sources. - for k, v := range a.extensions { + for k, v := range a.args.Extensions { event.SetExtension(k, v) } } - resp, err := a.sendMsg(ctx, a.sinkURI, (*binding.EventMessage)(event)) + response, err := a.sendMsg(ctx, a.args.SinkURI, (*binding.EventMessage)(event)) if err != nil { - a.logger.Error("Failed to send message to sink", zap.String("address", a.sinkURI), zap.Error(err)) + a.logger.Error("Failed to send message to sink", zap.String("address", a.args.SinkURI), zap.Error(err)) msg.Nack() return } - a.reporter.ReportEventCount(args, resp.StatusCode) + defer func() { + if err := response.Body.Close(); err != nil { + a.logger.Warn("Failed to close response body", zap.Error(err)) + } + }() + + a.reporter.ReportEventCount(args, response.StatusCode) - if resp.StatusCode/100 != 2 { - a.logger.Error("Event delivery failed", zap.Int("StatusCode", resp.StatusCode)) + if response.StatusCode/100 != 2 { + a.logger.Error("Event delivery failed", zap.Int("StatusCode", response.StatusCode)) msg.Nack() return } - if err := resp.Body.Close(); err != nil { - a.logger.Warn("Failed to close response body", zap.Error(err)) - } - msg.Ack() } @@ -246,11 +268,17 @@ func (a *Adapter) sendMsg(ctx context.Context, address string, msg binding.Messa } func (a *Adapter) startSpan(ctx context.Context, event *cev2.Event) (context.Context, *trace.Span) { + spanName := tracing.SourceDestination(a.namespacedName) + // This receive adapter code is used both for Sources and Channels. + // An ugly way to identify whether it was created from a Channel is to look at the resourceGroup. + if a.resourceGroup == messaging.ChannelsResource.String() { + spanName = tracing.ChannelDestination(a.namespacedName) + } var span *trace.Span if dt, ok := extensions.GetDistributedTracingExtension(*event); ok { - ctx, span = dt.StartChildSpan(ctx, tracing.ChannelMessagingDestination(a.namespacedResourceName)) + ctx, span = dt.StartChildSpan(ctx, spanName) } else { - ctx, span = trace.StartSpan(ctx, tracing.ChannelMessagingDestination(a.namespacedResourceName)) + ctx, span = trace.StartSpan(ctx, spanName) } if span.IsRecordingEvents() { span.AddAttributes( diff --git a/pkg/pubsub/adapter/converters/converters.go b/pkg/pubsub/adapter/converters/converters.go index 41e31d6a9f..0de9e0c8f1 100644 --- a/pkg/pubsub/adapter/converters/converters.go +++ b/pkg/pubsub/adapter/converters/converters.go @@ -41,6 +41,7 @@ const ( ) type ConverterType string +type ErrMissingAttribute error const ( // The different type of Converters for the different sources. diff --git a/pkg/pubsub/adapter/providers.go b/pkg/pubsub/adapter/providers.go index 2056b388e6..43deaa6921 100644 --- a/pkg/pubsub/adapter/providers.go +++ b/pkg/pubsub/adapter/providers.go @@ -18,6 +18,7 @@ type ResourceGroup string type SinkURI string type TransformerURI string type SubscriptionID string +type TopicID string // AdapterSet provides an adapter with a PubSub client and HTTP client. var AdapterSet wire.ProviderSet = wire.NewSet( diff --git a/pkg/tracing/attributes.go b/pkg/tracing/attributes.go index 64cc569250..e590a31ee2 100644 --- a/pkg/tracing/attributes.go +++ b/pkg/tracing/attributes.go @@ -30,6 +30,10 @@ var ( PubSubProtocolAttribute = tracing.MessagingProtocolAttribute(PubSubProtocol) ) -func ChannelMessagingDestination(c types.NamespacedName) string { +func ChannelDestination(c types.NamespacedName) string { return fmt.Sprintf("channel:%s.%s", c.Name, c.Namespace) } + +func SourceDestination(s types.NamespacedName) string { + return fmt.Sprintf("source:%s.%s", s.Name, s.Namespace) +} From 06cf5237f7e1ef5f16d48734ae2b22e94dd92e4f Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Mon, 22 Jun 2020 17:39:53 -0700 Subject: [PATCH 12/28] removing unnecessary stuff --- pkg/pubsub/adapter/converters/converters.go | 1 - pkg/pubsub/adapter/providers.go | 1 - 2 files changed, 2 deletions(-) diff --git a/pkg/pubsub/adapter/converters/converters.go b/pkg/pubsub/adapter/converters/converters.go index 0de9e0c8f1..41e31d6a9f 100644 --- a/pkg/pubsub/adapter/converters/converters.go +++ b/pkg/pubsub/adapter/converters/converters.go @@ -41,7 +41,6 @@ const ( ) type ConverterType string -type ErrMissingAttribute error const ( // The different type of Converters for the different sources. diff --git a/pkg/pubsub/adapter/providers.go b/pkg/pubsub/adapter/providers.go index 43deaa6921..2056b388e6 100644 --- a/pkg/pubsub/adapter/providers.go +++ b/pkg/pubsub/adapter/providers.go @@ -18,7 +18,6 @@ type ResourceGroup string type SinkURI string type TransformerURI string type SubscriptionID string -type TopicID string // AdapterSet provides an adapter with a PubSub client and HTTP client. var AdapterSet wire.ProviderSet = wire.NewSet( From bcce673e76d74b49f85a4616984c8bfadfe3cc0b Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Tue, 23 Jun 2020 07:48:35 -0700 Subject: [PATCH 13/28] better shutdown --- cmd/pubsub/receive_adapter/main.go | 17 ++++++++++++++--- pkg/pubsub/adapter/adapter.go | 28 +++------------------------- pkg/pubsub/publisher/publisher.go | 12 ++++++------ 3 files changed, 23 insertions(+), 34 deletions(-) diff --git a/cmd/pubsub/receive_adapter/main.go b/cmd/pubsub/receive_adapter/main.go index 1c5d2e72c3..c3cbea2cbc 100644 --- a/cmd/pubsub/receive_adapter/main.go +++ b/cmd/pubsub/receive_adapter/main.go @@ -19,6 +19,8 @@ package main import ( "flag" "fmt" + "time" + "go.uber.org/zap" "knative.dev/eventing/pkg/tracing" "knative.dev/pkg/logging" @@ -185,9 +187,18 @@ func main() { } logger.Info("Starting Receive Adapter.", zap.String("projectID", projectID), zap.String("topicID", env.Topic), zap.String("subscriptionID", env.Subscription)) - if err := adapter.Start(ctx); err != nil { - logging.FromContext(ctx).Error("Adapter has stopped with error", zap.String("projectID", projectID), zap.String("topicID", env.Topic), zap.String("subscriptionID", env.Subscription), zap.Error(err)) - } + adapter.Start(ctx, func(err error) { + if err != nil { + logger.Error("Adapter has stopped with error", zap.String("projectID", projectID), zap.String("topicID", env.Topic), zap.String("subscriptionID", env.Subscription), zap.Error(err)) + } else { + logger.Error("Adapter has stopped", zap.String("projectID", projectID), zap.String("topicID", env.Topic), zap.String("subscriptionID", env.Subscription), zap.Error(err)) + } + }) + + <-ctx.Done() + // Wait a grace period for the handlers to shutdown. + time.Sleep(30 * time.Second) + logger.Info("Exiting...") } diff --git a/pkg/pubsub/adapter/adapter.go b/pkg/pubsub/adapter/adapter.go index 96608ab293..cc628d68f0 100644 --- a/pkg/pubsub/adapter/adapter.go +++ b/pkg/pubsub/adapter/adapter.go @@ -18,10 +18,7 @@ package adapter import ( "context" - "errors" - "github.com/google/knative-gcp/pkg/apis/messaging" nethttp "net/http" - "time" "go.uber.org/zap" @@ -30,6 +27,7 @@ import ( "github.com/cloudevents/sdk-go/v2/binding" "github.com/cloudevents/sdk-go/v2/extensions" cehttp "github.com/cloudevents/sdk-go/v2/protocol/http" + "github.com/google/knative-gcp/pkg/apis/messaging" . "github.com/google/knative-gcp/pkg/pubsub/adapter/context" "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" "github.com/google/knative-gcp/pkg/tracing" @@ -117,37 +115,17 @@ func NewAdapter( } } -func (a *Adapter) Start(ctx context.Context) error { +func (a *Adapter) Start(ctx context.Context, done func(error)) { ctx, a.cancel = context.WithCancel(ctx) - defer a.cancel() // Augment context so that we can use it to create CE attributes. ctx = WithProjectKey(ctx, a.projectID) ctx = WithTopicKey(ctx, a.args.TopicID) ctx = WithSubscriptionKey(ctx, a.subscription.ID()) - errCh := make(chan error, 1) go func() { - errCh <- a.subscription.Receive(ctx, a.receive) + done(a.subscription.Receive(ctx, a.receive)) }() - - // Stop either if the adapter stops (sending to errCh) or if the context Done channel is closed. - select { - case err := <-errCh: - return err - case <-ctx.Done(): - break - } - - // Done channel has been closed, we need to gracefully shutdown. The cancel() method will start its - // shutdown, if it hasn't finished in a reasonable amount of time, just return an error. - a.cancel() - select { - case err := <-errCh: - return err - case <-time.After(30 * time.Second): - return errors.New("timeout shutting down adapter") - } } // Stop stops the adapter. diff --git a/pkg/pubsub/publisher/publisher.go b/pkg/pubsub/publisher/publisher.go index ecdf72924a..aa4a634752 100644 --- a/pkg/pubsub/publisher/publisher.go +++ b/pkg/pubsub/publisher/publisher.go @@ -65,9 +65,9 @@ type Publisher struct { // NewPublisher creates a new publisher. func NewPublisher(ctx context.Context, inbound HttpMessageReceiver, topic *pubsub.Topic) *Publisher { return &Publisher{ - inbound: inbound, - topic: topic, - logger: logging.FromContext(ctx), + inbound: inbound, + topic: topic, + logger: logging.FromContext(ctx), } } @@ -100,7 +100,7 @@ func (p *Publisher) ServeHTTP(response nethttp.ResponseWriter, request *nethttp. statusCode := nethttp.StatusAccepted ctx, cancel := context.WithTimeout(ctx, sinkTimeout) defer cancel() - if res := p.Publish(ctx, *event); !cev2.IsACK(res) { + if res := p.Publish(ctx, event); !cev2.IsACK(res) { msg := fmt.Sprintf("Error publishing to PubSub. event: %+v, err: %v.", event, res) p.logger.Error(msg) statusCode = nethttp.StatusInternalServerError @@ -111,10 +111,10 @@ func (p *Publisher) ServeHTTP(response nethttp.ResponseWriter, request *nethttp. } // Publish publishes an incoming event to a pubsub topic. -func (p *Publisher) Publish(ctx context.Context, event cev2.Event) protocol.Result { +func (p *Publisher) Publish(ctx context.Context, event *cev2.Event) protocol.Result { dt := extensions.FromSpanContext(trace.FromContext(ctx).SpanContext()) msg := new(pubsub.Message) - if err := cepubsub.WritePubSubMessage(ctx, binding.ToMessage(&event), msg, dt.WriteTransformer()); err != nil { + if err := cepubsub.WritePubSubMessage(ctx, binding.ToMessage(event), msg, dt.WriteTransformer()); err != nil { return err } _, err := p.topic.Publish(ctx, msg).Get(ctx) From a25046a6d217fc09181e09c8b67589b3159f68aa Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Tue, 23 Jun 2020 08:22:18 -0700 Subject: [PATCH 14/28] removing good_client and cesdk-v1 sender --- pkg/kncloudevents/good_client.go | 32 --------------------- test/test_images/sender/main.go | 49 +++++++++++++++++--------------- 2 files changed, 26 insertions(+), 55 deletions(-) delete mode 100644 pkg/kncloudevents/good_client.go diff --git a/pkg/kncloudevents/good_client.go b/pkg/kncloudevents/good_client.go deleted file mode 100644 index 2ed63d25f9..0000000000 --- a/pkg/kncloudevents/good_client.go +++ /dev/null @@ -1,32 +0,0 @@ -package kncloudevents - -import ( - cloudevents "github.com/cloudevents/sdk-go" - "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http" -) - -func NewDefaultClient(target ...string) (cloudevents.Client, error) { - tOpts := []http.Option{ - cloudevents.WithBinaryEncoding(), - } - if len(target) > 0 && target[0] != "" { - tOpts = append(tOpts, cloudevents.WithTarget(target[0])) - } - - // Make an http transport for the CloudEvents client. - t, err := cloudevents.NewHTTPTransport(tOpts...) - if err != nil { - return nil, err - } - - // Use the transport to make a new CloudEvents client. - c, err := cloudevents.NewClient(t, - cloudevents.WithUUIDs(), - cloudevents.WithTimeNow(), - ) - - if err != nil { - return nil, err - } - return c, nil -} diff --git a/test/test_images/sender/main.go b/test/test_images/sender/main.go index 7baa0a504a..3daca2a6aa 100644 --- a/test/test_images/sender/main.go +++ b/test/test_images/sender/main.go @@ -21,11 +21,9 @@ import ( "encoding/json" "fmt" "io/ioutil" - "net/http" "os" - cloudevents "github.com/cloudevents/sdk-go" - "github.com/google/knative-gcp/pkg/kncloudevents" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/knative-gcp/test/e2e/lib" "go.opencensus.io/trace" ) @@ -37,25 +35,40 @@ const ( func main() { brokerURL := os.Getenv(brokerURLEnvVar) - ceClient, err := kncloudevents.NewDefaultClient(brokerURL) + t, err := cloudevents.NewHTTP(cloudevents.WithTarget(brokerURL)) if err != nil { - fmt.Printf("Unable to create ceClient: %s ", err) + fmt.Printf("Unable to create transport: %v ", err) + os.Exit(1) } - ctx, span := trace.StartSpan(context.Background(), "sender", trace.WithSampler(trace.AlwaysSample())) - defer span.End() + c, err := cloudevents.NewClient(t, + cloudevents.WithTimeNow(), + cloudevents.WithUUIDs(), + ) - ctx, _, err = ceClient.Send(ctx, dummyCloudEvent()) - rtctx := cloudevents.HTTPTransportContextFrom(ctx) if err != nil { - fmt.Print(err) + fmt.Printf("Unable to create client: %v", err) + os.Exit(1) } + + ctx, span := trace.StartSpan(context.Background(), "sender", trace.WithSampler(trace.AlwaysSample())) + defer span.End() + + event := cloudevents.NewEvent(cloudevents.VersionV1) + event.SetID(lib.E2EDummyEventID) + event.SetType(lib.E2EDummyEventType) + event.SetSource(lib.E2EDummyEventSource) + event.SetDataContentType(cloudevents.ApplicationJSON) + event.SetData(cloudevents.ApplicationJSON, `{"source": "sender!"}`) + var success bool - if rtctx.StatusCode >= http.StatusOK && rtctx.StatusCode < http.StatusBadRequest { - success = true - } else { + if res := c.Send(ctx, event); !cloudevents.IsACK(res) { + fmt.Printf("Failed to send event to %s: %s\n", brokerURL, res.Error()) success = false + } else { + success = true } + if err := writeTerminationMessage(map[string]interface{}{ "success": success, "traceid": span.SpanContext().TraceID.String(), @@ -64,16 +77,6 @@ func main() { } } -func dummyCloudEvent() cloudevents.Event { - event := cloudevents.NewEvent(cloudevents.VersionV1) - event.SetID(lib.E2EDummyEventID) - event.SetType(lib.E2EDummyEventType) - event.SetSource(lib.E2EDummyEventSource) - event.SetDataContentType(cloudevents.ApplicationJSON) - event.SetData(`{"source": "sender!"}`) - return event -} - func writeTerminationMessage(result interface{}) error { b, err := json.Marshal(result) if err != nil { From a9ad6a247f5abb3669c0eb04ffae55fc122f4aa5 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Tue, 23 Jun 2020 10:21:46 -0700 Subject: [PATCH 15/28] moving e2e tests to cev2 --- test/test_images/auditlogs_receiver/main.go | 32 ++++++++----------- test/test_images/auditlogs_target/main.go | 4 +-- .../internal/knockdown/knockdown.go | 2 +- test/test_images/pubsub_receiver/main.go | 27 +++++++--------- test/test_images/pubsub_target/main.go | 2 +- test/test_images/scheduler_receiver/main.go | 29 +++++++---------- test/test_images/scheduler_target/main.go | 4 +-- test/test_images/storage_receiver/main.go | 30 ++++++++--------- test/test_images/storage_target/main.go | 2 +- 9 files changed, 57 insertions(+), 75 deletions(-) diff --git a/test/test_images/auditlogs_receiver/main.go b/test/test_images/auditlogs_receiver/main.go index cb54e4e7bf..d5470da2ed 100644 --- a/test/test_images/auditlogs_receiver/main.go +++ b/test/test_images/auditlogs_receiver/main.go @@ -19,12 +19,10 @@ package main import ( "context" "fmt" - "log" - "net/http" - - cloudevents "github.com/cloudevents/sdk-go" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/knative-gcp/pkg/apis/events/v1beta1" "github.com/google/knative-gcp/test/e2e/lib" + "log" ) type Receiver struct { @@ -44,25 +42,23 @@ func main() { } } -func (r *Receiver) Receive(ctx context.Context, event cloudevents.Event, resp *cloudevents.EventResponse) { +func (r *Receiver) Receive(event cloudevents.Event) (*cloudevents.Event, error) { // Check if the received event is the event sent by CloudAuditLogsSource. // If it is, send back a response CloudEvent. // Print out event received to log fmt.Printf("auditlogs receiver received event\n") fmt.Printf("context of event is: %v\n", event.Context.String()) - if event.Type() == v1beta1.CloudAuditLogsSourceEvent { - resp.Status = http.StatusAccepted - respEvent := cloudevents.NewEvent(cloudevents.VersionV1) - respEvent.SetID(lib.E2EAuditLogsRespEventID) - respEvent.SetType(lib.E2EAuditLogsRespType) - respEvent.SetSource(event.Source()) - respEvent.SetSubject(event.Subject()) - respEvent.SetData(event.Data) - respEvent.SetDataContentType(event.DataContentType()) - fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) - resp.Event = &respEvent - } else { - resp.Status = http.StatusForbidden + if event.Type() != v1beta1.CloudAuditLogsSourceEvent { + return nil, fmt.Errorf("unexpected cloud event type got=%s, want=%s", event.Type(), v1beta1.CloudAuditLogsSourceEvent) } + respEvent := cloudevents.NewEvent(cloudevents.VersionV1) + respEvent.SetID(lib.E2EAuditLogsRespEventID) + respEvent.SetType(lib.E2EAuditLogsRespType) + respEvent.SetSource(event.Source()) + respEvent.SetSubject(event.Subject()) + respEvent.SetData(event.DataContentType(), event.Data) + fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) + return &respEvent, nil + } diff --git a/test/test_images/auditlogs_target/main.go b/test/test_images/auditlogs_target/main.go index 317d0826cd..6463023e66 100644 --- a/test/test_images/auditlogs_target/main.go +++ b/test/test_images/auditlogs_target/main.go @@ -21,7 +21,7 @@ import ( "fmt" "os" - cloudevents "github.com/cloudevents/sdk-go" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/knative-gcp/test/e2e/lib" "github.com/google/knative-gcp/test/test_images/internal/knockdown" "github.com/kelseyhightower/envconfig" @@ -70,7 +70,7 @@ func (r *auditLogReceiver) Knockdown(event cloudevents.Event) bool { fmt.Printf("event.Context is %s", event.Context.String()) var eventData map[string]interface{} - if err := json.Unmarshal(event.Data.([]byte), &eventData); err != nil { + if err := json.Unmarshal(event.Data(), &eventData); err != nil { fmt.Printf("failed unmarshall event.Data %s.\n", err.Error()) } payload := eventData[protoPayload].(map[string]interface{}) diff --git a/test/test_images/internal/knockdown/knockdown.go b/test/test_images/internal/knockdown/knockdown.go index 48bcbee014..1cf5d5f947 100644 --- a/test/test_images/internal/knockdown/knockdown.go +++ b/test/test_images/internal/knockdown/knockdown.go @@ -24,7 +24,7 @@ import ( "log" "time" - cloudevents "github.com/cloudevents/sdk-go" + cloudevents "github.com/cloudevents/sdk-go/v2" ) // Config is a common envconfig filled struct that includes the common options for knockdown diff --git a/test/test_images/pubsub_receiver/main.go b/test/test_images/pubsub_receiver/main.go index e9eb8a1cac..d3b513b573 100644 --- a/test/test_images/pubsub_receiver/main.go +++ b/test/test_images/pubsub_receiver/main.go @@ -20,11 +20,9 @@ import ( "context" "fmt" "log" - "net/http" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/knative-gcp/pkg/apis/events/v1beta1" - - cloudevents "github.com/cloudevents/sdk-go" "github.com/google/knative-gcp/test/e2e/lib" ) @@ -45,24 +43,21 @@ func main() { } } -func (r *Receiver) Receive(ctx context.Context, event cloudevents.Event, resp *cloudevents.EventResponse) { +func (r *Receiver) Receive(event cloudevents.Event) (*cloudevents.Event, error) { // Check if the received event is the event sent by CloudPubSubSource. // If it is, send back a response CloudEvent. // Print out event received to log fmt.Printf("pubsub receiver received event\n") fmt.Printf("context of event is: %v\n", event.Context.String()) - if event.Type() == v1beta1.CloudPubSubSourcePublish { - resp.Status = http.StatusAccepted - respEvent := cloudevents.NewEvent(cloudevents.VersionV1) - respEvent.SetID(lib.E2EPubSubRespEventID) - respEvent.SetType(lib.E2EPubSubRespEventType) - respEvent.SetSource(event.Source()) - respEvent.SetDataContentType(event.DataContentType()) - respEvent.SetData(`{"source": "pubsub"}`) - fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) - resp.Event = &respEvent - } else { - resp.Status = http.StatusForbidden + if event.Type() != v1beta1.CloudPubSubSourcePublish { + return nil, fmt.Errorf("unexpected cloud event type got=%s, want=%s", event.Type(), v1beta1.CloudPubSubSourcePublish) } + respEvent := cloudevents.NewEvent(cloudevents.VersionV1) + respEvent.SetID(lib.E2EPubSubRespEventID) + respEvent.SetType(lib.E2EPubSubRespEventType) + respEvent.SetSource(event.Source()) + respEvent.SetData(event.DataContentType(), `{"source": "pubsub"}`) + fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) + return &respEvent, nil } diff --git a/test/test_images/pubsub_target/main.go b/test/test_images/pubsub_target/main.go index f50cd6b23e..f97adc99d0 100644 --- a/test/test_images/pubsub_target/main.go +++ b/test/test_images/pubsub_target/main.go @@ -20,7 +20,7 @@ import ( "fmt" "os" - cloudevents "github.com/cloudevents/sdk-go" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/knative-gcp/test/e2e/lib" "github.com/google/knative-gcp/test/test_images/internal/knockdown" "github.com/kelseyhightower/envconfig" diff --git a/test/test_images/scheduler_receiver/main.go b/test/test_images/scheduler_receiver/main.go index bce6bcab88..24f848a82c 100644 --- a/test/test_images/scheduler_receiver/main.go +++ b/test/test_images/scheduler_receiver/main.go @@ -20,11 +20,9 @@ import ( "context" "fmt" "log" - "net/http" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/knative-gcp/pkg/apis/events/v1beta1" - - cloudevents "github.com/cloudevents/sdk-go" "github.com/google/knative-gcp/test/e2e/lib" ) @@ -45,25 +43,22 @@ func main() { } } -func (r *Receiver) Receive(ctx context.Context, event cloudevents.Event, resp *cloudevents.EventResponse) { +func (r *Receiver) Receive(event cloudevents.Event) (*cloudevents.Event, error) { // Check if the received event is the event sent by CloudSchedulerSource. // If it is, send back a response CloudEvent. // Print out event received to log fmt.Printf("scheduler receiver received event\n") fmt.Printf("context of event is: %v\n", event.Context.String()) - if event.Type() == v1beta1.CloudSchedulerSourceExecute { - resp.Status = http.StatusAccepted - respEvent := cloudevents.NewEvent(cloudevents.VersionV1) - respEvent.SetID(lib.E2ESchedulerRespEventID) - respEvent.SetType(lib.E2ESchedulerRespType) - respEvent.SetSource(event.Source()) - respEvent.SetSubject(event.Subject()) - respEvent.SetData(event.Data) - respEvent.SetDataContentType(event.DataContentType()) - fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) - resp.Event = &respEvent - } else { - resp.Status = http.StatusForbidden + if event.Type() != v1beta1.CloudSchedulerSourceExecute { + return nil, fmt.Errorf("unexpected cloud event type got=%s, want=%s", event.Type(), v1beta1.CloudSchedulerSourceExecute) } + respEvent := cloudevents.NewEvent(cloudevents.VersionV1) + respEvent.SetID(lib.E2ESchedulerRespEventID) + respEvent.SetType(lib.E2ESchedulerRespType) + respEvent.SetSource(event.Source()) + respEvent.SetSubject(event.Subject()) + respEvent.SetData(event.DataContentType(), event.Data) + fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) + return &respEvent, nil } diff --git a/test/test_images/scheduler_target/main.go b/test/test_images/scheduler_target/main.go index ca13956238..4a6d4ccdab 100644 --- a/test/test_images/scheduler_target/main.go +++ b/test/test_images/scheduler_target/main.go @@ -5,7 +5,7 @@ import ( "os" "strings" - cloudevents "github.com/cloudevents/sdk-go" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/knative-gcp/test/e2e/lib" "github.com/google/knative-gcp/test/test_images/internal/knockdown" "github.com/kelseyhightower/envconfig" @@ -55,7 +55,7 @@ func (r *schedulerReceiver) Knockdown(event cloudevents.Event) bool { } // Check data - data := string(event.Data.([]uint8)) + data := string(event.Data()) if data != r.Data { incorrectAttributes[lib.EventData] = lib.PropPair{Expected: r.Data, Received: data} } diff --git a/test/test_images/storage_receiver/main.go b/test/test_images/storage_receiver/main.go index 44a06bd8ca..e74f2178ca 100644 --- a/test/test_images/storage_receiver/main.go +++ b/test/test_images/storage_receiver/main.go @@ -19,12 +19,10 @@ package main import ( "context" "fmt" - "log" - "net/http" - - cloudevents "github.com/cloudevents/sdk-go" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/knative-gcp/pkg/apis/events/v1beta1" "github.com/google/knative-gcp/test/e2e/lib" + "log" ) type Receiver struct { @@ -44,24 +42,22 @@ func main() { } } -func (r *Receiver) Receive(ctx context.Context, event cloudevents.Event, resp *cloudevents.EventResponse) { +func (r *Receiver) Receive(event cloudevents.Event) (*cloudevents.Event, error) { // Check if the received event is the event sent by CloudStorageSource. // If it is, send back a response CloudEvent. // Print out event received to log fmt.Printf("storage receiver received event\n") fmt.Printf("context of event is: %v\n", event.Context.String()) - if event.Type() == v1beta1.CloudStorageSourceFinalize { - resp.Status = http.StatusAccepted - respEvent := cloudevents.NewEvent(cloudevents.VersionV1) - respEvent.SetID(lib.E2EStorageRespEventID) - respEvent.SetType(lib.E2EStorageRespEventType) - respEvent.SetSource(event.Source()) - respEvent.SetSubject(event.Subject()) - respEvent.SetDataContentType(event.DataContentType()) - fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) - resp.Event = &respEvent - } else { - resp.Status = http.StatusForbidden + if event.Type() != v1beta1.CloudStorageSourceFinalize { + return nil, fmt.Errorf("unexpected cloud event type got=%s, want=%s", event.Type(), v1beta1.CloudStorageSourceFinalize) } + respEvent := cloudevents.NewEvent(cloudevents.VersionV1) + respEvent.SetID(lib.E2EStorageRespEventID) + respEvent.SetType(lib.E2EStorageRespEventType) + respEvent.SetSource(event.Source()) + respEvent.SetSubject(event.Subject()) + respEvent.SetData(event.DataContentType(), `{"source": "storage"}`) + fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) + return &respEvent, nil } diff --git a/test/test_images/storage_target/main.go b/test/test_images/storage_target/main.go index 62f0701feb..e3f2df843d 100644 --- a/test/test_images/storage_target/main.go +++ b/test/test_images/storage_target/main.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - cloudevents "github.com/cloudevents/sdk-go" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/knative-gcp/test/e2e/lib" "github.com/google/knative-gcp/test/test_images/internal/knockdown" "github.com/kelseyhightower/envconfig" From 0d2bd1dcf19aa12c3542bb34a72be6a6c1a8a71b Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Tue, 23 Jun 2020 10:46:27 -0700 Subject: [PATCH 16/28] updates to tests --- test/test_images/pubsub_receiver/main.go | 2 +- test/test_images/receiver/main.go | 22 +++++++++++----------- test/test_images/storage_receiver/main.go | 2 +- test/test_images/target/main.go | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/test/test_images/pubsub_receiver/main.go b/test/test_images/pubsub_receiver/main.go index d3b513b573..bdb417c3e9 100644 --- a/test/test_images/pubsub_receiver/main.go +++ b/test/test_images/pubsub_receiver/main.go @@ -57,7 +57,7 @@ func (r *Receiver) Receive(event cloudevents.Event) (*cloudevents.Event, error) respEvent.SetID(lib.E2EPubSubRespEventID) respEvent.SetType(lib.E2EPubSubRespEventType) respEvent.SetSource(event.Source()) - respEvent.SetData(event.DataContentType(), `{"source": "pubsub"}`) + respEvent.SetData(cloudevents.ApplicationJSON, `{"source": "pubsub"}`) fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) return &respEvent, nil } diff --git a/test/test_images/receiver/main.go b/test/test_images/receiver/main.go index c345be8e31..7228a613d0 100644 --- a/test/test_images/receiver/main.go +++ b/test/test_images/receiver/main.go @@ -18,10 +18,12 @@ package main import ( "context" + "fmt" + "github.com/google/knative-gcp/pkg/apis/events/v1beta1" "log" "net/http" - cloudevents "github.com/cloudevents/sdk-go" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/knative-gcp/test/e2e/lib" ) @@ -42,19 +44,17 @@ func main() { } } -func (r *Receiver) Receive(ctx context.Context, event cloudevents.Event, resp *cloudevents.EventResponse) { - // Check if the received event is the dummy event sent by sender pod. +func (r *Receiver) Receive(event cloudevents.Event) (*cloudevents.Event, error) { + // Check if the received event is the dummy event sent by sender pod.&event, nil // If it is, send back a response CloudEvent. - if event.ID() == lib.E2EDummyEventID { - resp.Status = http.StatusAccepted + if event.ID() != lib.E2EDummyEventID { + return nil, fmt.Errorf("unexpected cloud event id got=%s, want=%s", event.ID(), lib.E2EDummyEventID) + } event = cloudevents.NewEvent(cloudevents.VersionV1) event.SetID(lib.E2EDummyRespEventID) event.SetType(lib.E2EDummyRespEventType) event.SetSource(lib.E2EDummyRespEventSource) - event.SetDataContentType(cloudevents.ApplicationJSON) - event.SetData(`{"source": "receiver!"}`) - resp.Event = &event - } else { - resp.Status = http.StatusForbidden - } + event.SetData(cloudevents.ApplicationJSON, `{"source": "receiver!"}`) + return + } diff --git a/test/test_images/storage_receiver/main.go b/test/test_images/storage_receiver/main.go index e74f2178ca..b99b397fef 100644 --- a/test/test_images/storage_receiver/main.go +++ b/test/test_images/storage_receiver/main.go @@ -57,7 +57,7 @@ func (r *Receiver) Receive(event cloudevents.Event) (*cloudevents.Event, error) respEvent.SetType(lib.E2EStorageRespEventType) respEvent.SetSource(event.Source()) respEvent.SetSubject(event.Subject()) - respEvent.SetData(event.DataContentType(), `{"source": "storage"}`) + respEvent.SetData(cloudevents.ApplicationJSON, `{"source": "storage"}`) fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) return &respEvent, nil } diff --git a/test/test_images/target/main.go b/test/test_images/target/main.go index 1c0f1b824a..5cde315960 100644 --- a/test/test_images/target/main.go +++ b/test/test_images/target/main.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - cloudevents "github.com/cloudevents/sdk-go" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/knative-gcp/test/e2e/lib" "github.com/google/knative-gcp/test/test_images/internal/knockdown" "github.com/kelseyhightower/envconfig" From d44ee4c8466c0e25f9fe1a0656835f417551f912 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Tue, 23 Jun 2020 10:53:51 -0700 Subject: [PATCH 17/28] update-codegen --- .../cloudevents/sdk-go/{ => pkg/cloudevents/types}/LICENSE | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/{ => pkg/cloudevents/types}/LICENSE (100%) diff --git a/third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/LICENSE b/third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/pkg/cloudevents/types/LICENSE similarity index 100% rename from third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/LICENSE rename to third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/pkg/cloudevents/types/LICENSE From e3ae81e98bf856a5d8bfd2b4a13127fa6e87995e Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Tue, 23 Jun 2020 11:59:29 -0700 Subject: [PATCH 18/28] code review comments, and updating deps, trying to get rid of cev1... seems that is still there... --- go.mod | 9 +- go.sum | 35 +- pkg/broker/eventutil/hops.go | 2 +- .../broker/v1beta1/broker/reconciler.go | 4 + .../broker/v1beta1/trigger/reconciler.go | 4 + .../cloudauditlogssource/reconciler.go | 4 + .../v1alpha1/cloudbuildsource/reconciler.go | 4 + .../v1alpha1/cloudpubsubsource/reconciler.go | 4 + .../cloudschedulersource/reconciler.go | 4 + .../v1alpha1/cloudstoragesource/reconciler.go | 4 + .../cloudauditlogssource/reconciler.go | 4 + .../v1beta1/cloudbuildsource/reconciler.go | 4 + .../v1beta1/cloudpubsubsource/reconciler.go | 4 + .../cloudschedulersource/reconciler.go | 4 + .../v1beta1/cloudstoragesource/reconciler.go | 4 + .../v1alpha1/brokercell/reconciler.go | 4 + .../v1alpha1/pullsubscription/reconciler.go | 4 + .../intevents/v1alpha1/topic/reconciler.go | 4 + .../v1beta1/pullsubscription/reconciler.go | 4 + .../intevents/v1beta1/topic/reconciler.go | 4 + .../messaging/v1alpha1/channel/reconciler.go | 4 + .../messaging/v1beta1/channel/reconciler.go | 4 + pkg/pubsub/adapter/adapter.go | 2 +- pkg/pubsub/adapter/converters/pubsub_test.go | 20 +- .../resources/receive_adapter_test.go | 15 +- pkg/tracing/attributes.go | 9 +- .../sdk-go/pkg/cloudevents/types/LICENSE | 201 ---------- .../github.com/cloudevents/sdk-go/.gitignore | 2 +- .../github.com/cloudevents/sdk-go/README.md | 20 +- vendor/github.com/cloudevents/sdk-go/alias.go | 13 +- vendor/github.com/cloudevents/sdk-go/go.mod | 9 +- vendor/github.com/cloudevents/sdk-go/go.sum | 32 -- .../sdk-go/pkg/cloudevents/client/client.go | 42 +-- .../pkg/cloudevents/client/observability.go | 42 +-- .../sdk-go/pkg/cloudevents/client/options.go | 9 - .../datacodec/json/observability.go | 12 + .../cloudevents/datacodec/observability.go | 12 + .../datacodec/xml/observability.go | 12 + .../sdk-go/pkg/cloudevents/event.go | 2 +- .../pkg/cloudevents/event_observability.go | 17 + .../pkg/cloudevents/eventcontext_v01.go | 16 +- .../pkg/cloudevents/eventcontext_v02.go | 16 +- .../pkg/cloudevents/eventcontext_v03.go | 16 +- .../sdk-go/pkg/cloudevents/eventcontext_v1.go | 16 +- .../distributed_tracing_extension.go | 135 ------- .../pkg/cloudevents/observability/observer.go | 34 +- .../pkg/cloudevents/transport/http/codec.go | 4 +- .../pkg/cloudevents/transport/http/context.go | 5 - .../transport/http/observability.go | 23 ++ .../pkg/cloudevents/transport/http/options.go | 12 +- .../cloudevents/transport/http/transport.go | 48 +-- .../pkg/cloudevents/transport/transport.go | 5 - vendor/gopkg.in/yaml.v3/.travis.yml | 2 +- vendor/gopkg.in/yaml.v3/decode.go | 40 +- vendor/gopkg.in/yaml.v3/emitterc.go | 53 ++- vendor/gopkg.in/yaml.v3/encode.go | 6 +- vendor/gopkg.in/yaml.v3/scannerc.go | 39 +- vendor/gopkg.in/yaml.v3/yamlh.go | 3 +- .../pkg/apis/duck/v1/channelable_types.go | 152 ++++++++ .../pkg/apis/duck/v1/delivery_conversion.go | 44 +++ .../pkg/apis/duck/v1/delivery_types.go | 95 +++++ .../eventing/pkg/apis/duck/v1/doc.go | 24 ++ .../pkg/apis/duck/v1/subscribable_types.go | 157 ++++++++ .../duck/v1/subscribable_types_conversion.go | 34 ++ .../pkg/apis/duck/v1/zz_generated.deepcopy.go | 343 ++++++++++++++++++ .../v1alpha1/subscribable_types_conversion.go | 8 +- .../apis/duck/v1beta1/delivery_conversion.go | 60 ++- .../v1beta1/subscribable_types_conversion.go | 105 +++++- .../pkg/apis/eventing/v1/broker_conversion.go | 34 ++ .../pkg/apis/eventing/v1/broker_defaults.go | 47 +++ .../pkg/apis/eventing/v1/broker_lifecycle.go | 114 ++++++ .../pkg/apis/eventing/v1/broker_types.go | 119 ++++++ .../pkg/apis/eventing/v1/broker_validation.go | 76 ++++ .../eventing/pkg/apis/eventing/v1/doc.go | 20 + .../eventing/pkg/apis/eventing/v1/register.go | 55 +++ .../pkg/apis/eventing/v1/test_helper.go | 122 +++++++ .../apis/eventing/v1/trigger_conversion.go | 34 ++ .../pkg/apis/eventing/v1/trigger_defaults.go | 52 +++ .../pkg/apis/eventing/v1/trigger_lifecycle.go | 187 ++++++++++ .../pkg/apis/eventing/v1/trigger_types.go | 130 +++++++ .../apis/eventing/v1/trigger_validation.go | 155 ++++++++ .../apis/eventing/v1/zz_generated.deepcopy.go | 283 +++++++++++++++ .../eventing/v1beta1/broker_conversion.go | 31 +- .../eventing/v1beta1/eventtype_conversion.go | 8 +- .../eventing/v1beta1/trigger_conversion.go | 39 +- .../pkg/apis/sources/v1alpha1/ping_types.go | 1 - .../client/clientset/versioned/clientset.go | 14 + .../versioned/fake/clientset_generated.go | 7 + .../clientset/versioned/fake/register.go | 2 + .../clientset/versioned/scheme/register.go | 2 + .../versioned/typed/eventing/v1/broker.go | 191 ++++++++++ .../versioned/typed/eventing/v1/doc.go | 20 + .../typed/eventing/v1/eventing_client.go | 94 +++++ .../versioned/typed/eventing/v1/fake/doc.go | 20 + .../typed/eventing/v1/fake/fake_broker.go | 140 +++++++ .../eventing/v1/fake/fake_eventing_client.go | 44 +++ .../typed/eventing/v1/fake/fake_trigger.go | 140 +++++++ .../typed/eventing/v1/generated_expansion.go | 23 ++ .../versioned/typed/eventing/v1/trigger.go | 191 ++++++++++ .../externalversions/eventing/interface.go | 8 + .../externalversions/eventing/v1/broker.go | 89 +++++ .../externalversions/eventing/v1/interface.go | 52 +++ .../externalversions/eventing/v1/trigger.go | 89 +++++ .../informers/externalversions/generic.go | 7 + .../eventing/v1beta1/broker/controller.go | 23 +- .../eventing/v1beta1/broker/reconciler.go | 120 ++++-- .../pkg/client/listers/eventing/v1/broker.go | 94 +++++ .../eventing/v1/expansion_generated.go | 35 ++ .../pkg/client/listers/eventing/v1/trigger.go | 94 +++++ ...hannel_message_modes_specversion_helper.go | 113 ++++++ .../source_crd_metadata_test_helper.go | 48 +++ vendor/knative.dev/eventing/test/e2e-tests.sh | 2 +- vendor/knative.dev/eventing/test/e2e_flags.go | 4 + .../eventing/test/flags/channels.go | 20 +- .../test/flags/eventing_environment.go | 1 + .../eventing/test/flags/parsing.go | 47 +++ .../eventing/test/flags/sources.go | 42 +++ .../lib/recordevents/event_info_matchers.go | 10 + .../test/lib/recordevents/event_info_store.go | 29 +- vendor/knative.dev/pkg/apis/duck/register.go | 8 + .../cmd/injection-gen/generators/packages.go | 2 +- .../pkg/configmap/manual_watcher.go | 14 +- vendor/knative.dev/pkg/test/gcs/gcs.go | 12 +- vendor/knative.dev/pkg/test/spoof/spoof.go | 4 +- .../clustermanager/perf-tests/main.go | 13 +- .../clustermanager/perf-tests/pkg/cluster.go | 13 + vendor/knative.dev/pkg/tracing/http.go | 2 + .../propagation/http_format_sequence.go | 53 +++ .../propagation/tracecontextb3/http_format.go | 61 ++++ vendor/knative.dev/pkg/webhook/conversion.go | 4 + .../apis/autoscaling/annotation_validation.go | 2 +- vendor/modules.txt | 24 +- 132 files changed, 4838 insertions(+), 784 deletions(-) delete mode 100644 third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/pkg/cloudevents/types/LICENSE delete mode 100644 vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/extensions/distributed_tracing_extension.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/duck/v1/channelable_types.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/duck/v1/delivery_conversion.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/duck/v1/delivery_types.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/duck/v1/doc.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/duck/v1/subscribable_types.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/duck/v1/subscribable_types_conversion.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/duck/v1/zz_generated.deepcopy.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_conversion.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_defaults.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_lifecycle.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_types.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_validation.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/eventing/v1/doc.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/eventing/v1/register.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/eventing/v1/test_helper.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_conversion.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_defaults.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_lifecycle.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_types.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_validation.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/eventing/v1/zz_generated.deepcopy.go create mode 100644 vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/broker.go create mode 100644 vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/doc.go create mode 100644 vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/eventing_client.go create mode 100644 vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/doc.go create mode 100644 vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/fake_broker.go create mode 100644 vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/fake_eventing_client.go create mode 100644 vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/fake_trigger.go create mode 100644 vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/generated_expansion.go create mode 100644 vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/trigger.go create mode 100644 vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1/broker.go create mode 100644 vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1/interface.go create mode 100644 vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1/trigger.go create mode 100644 vendor/knative.dev/eventing/pkg/client/listers/eventing/v1/broker.go create mode 100644 vendor/knative.dev/eventing/pkg/client/listers/eventing/v1/expansion_generated.go create mode 100644 vendor/knative.dev/eventing/pkg/client/listers/eventing/v1/trigger.go create mode 100644 vendor/knative.dev/eventing/test/conformance/helpers/channel_message_modes_specversion_helper.go create mode 100644 vendor/knative.dev/eventing/test/conformance/helpers/source_crd_metadata_test_helper.go create mode 100644 vendor/knative.dev/eventing/test/flags/parsing.go create mode 100644 vendor/knative.dev/eventing/test/flags/sources.go create mode 100644 vendor/knative.dev/pkg/tracing/propagation/http_format_sequence.go create mode 100644 vendor/knative.dev/pkg/tracing/propagation/tracecontextb3/http_format.go diff --git a/go.mod b/go.mod index 13de6970ce..4a4976f3d6 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( cloud.google.com/go/logging v1.0.1-0.20200331222814-69e77e66e597 cloud.google.com/go/pubsub v1.3.2-0.20200506222144-2c46308f8465 cloud.google.com/go/storage v1.8.0 - github.com/cloudevents/sdk-go v1.2.0 + github.com/cloudevents/sdk-go v1.0.0 github.com/cloudevents/sdk-go/protocol/pubsub/v2 v2.0.1-0.20200602143929-d07dc0510d45 github.com/cloudevents/sdk-go/v2 v2.0.1-0.20200608152019-2ab697c8fc0b github.com/fsnotify/fsnotify v1.4.9 @@ -31,9 +31,10 @@ require ( k8s.io/api v0.18.1 k8s.io/apimachinery v0.18.1 k8s.io/client-go v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible - knative.dev/eventing v0.15.1-0.20200619221325-e8ca69f837c7 - knative.dev/pkg v0.0.0-20200622015826-5e60b6f8633c - knative.dev/serving v0.15.1-0.20200621202726-40edbdd01f1c + knative.dev/eventing v0.15.1-0.20200623172931-13e513727e77 + knative.dev/pkg v0.0.0-20200623173527-5658d93fb07e + knative.dev/serving v0.15.1-0.20200623164334-a956ab8df9fa + knative.dev/test-infra v0.0.0-20200623145727-e9ff5263be06 // indirect sigs.k8s.io/yaml v1.2.0 ) diff --git a/go.sum b/go.sum index 6b413a4b34..ad1aa26516 100644 --- a/go.sum +++ b/go.sum @@ -141,7 +141,6 @@ github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jB github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= @@ -225,9 +224,8 @@ github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575/go.mod h1:9d6lWj8KzO/ github.com/clarketm/json v1.13.4/go.mod h1:ynr2LRfb0fQU34l07csRNBTcivjySLLiY1YzQqKVfdo= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudevents/sdk-go v0.0.0-20190509003705-56931988abe3/go.mod h1:j1nZWMLGg3om8SswStBoY6/SHvcLM19MuZqwDtMtmzs= +github.com/cloudevents/sdk-go v1.0.0 h1:gS5I0s2qPmdc4GBPlUmzZU7RH30BaiOdcRJ1RkXnPrc= github.com/cloudevents/sdk-go v1.0.0/go.mod h1:3TkmM0cFqkhCHOq5JzzRU/RxRkwzoS8TZ+G448qVTog= -github.com/cloudevents/sdk-go v1.2.0 h1:2AxI14EJUw1PclJ5gZJtzbxnHIfNMdi76Qq3P3G1BRU= -github.com/cloudevents/sdk-go v1.2.0/go.mod h1:ss+jWJ88wypiewnPEzChSBzTYXGpdcILoN9YHk8uhTQ= github.com/cloudevents/sdk-go/protocol/pubsub/v2 v2.0.1-0.20200602143929-d07dc0510d45 h1:BcfQO+2WfZp1SsjCQdu07Ksb+VGbqLR4FUqJ+LUE1ko= github.com/cloudevents/sdk-go/protocol/pubsub/v2 v2.0.1-0.20200602143929-d07dc0510d45/go.mod h1:KyGtbsR84tpP870ydX77lvHVq++zh3iUoY9dzUxj+cM= github.com/cloudevents/sdk-go/v2 v2.0.0 h1:AUdGJwaSUnA+VvepKqgjy6XDkPcf0hf/3L7icEs1ibs= @@ -665,7 +663,6 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kubernetes-incubator/custom-metrics-apiserver v0.0.0-20190918110929-3d9be26a50eb/go.mod h1:KWRxWvzVCNvDtG9ejU5UdpgvxdCZFMUZu0xroKWG8Bo= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= @@ -1043,7 +1040,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6 h1:TjszyFsQsyZNHwdVdZ5m7bjmreu0znc2kRYsEml9/Ww= @@ -1469,6 +1465,8 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22 h1:0efs3hwEZhFKsCoP8l6dDB1AZWMgnEl3yWXWRZTOaEA= gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d h1:LCPbGQ34PMrwad11aMZ+dbz5SAsq/0ySjRwQ8I9Qwd8= +gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= helm.sh/helm/v3 v3.1.1/go.mod h1:WYsFJuMASa/4XUqLyv54s0U/f3mlAaRErGmyy4z921g= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= @@ -1524,7 +1522,6 @@ k8s.io/kubernetes v1.14.7/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/legacy-cloud-providers v0.17.0/go.mod h1:DdzaepJ3RtRy+e5YhNtrCYwlgyK87j/5+Yfp0L9Syp8= k8s.io/legacy-cloud-providers v0.17.4/go.mod h1:FikRNoD64ECjkxO36gkDgJeiQWwyZTuBkhu+yxOc1Js= k8s.io/metrics v0.17.2/go.mod h1:3TkNHET4ROd+NfzNxkjoVfQ0Ob4iZnaHmSEA4vYpwLw= -k8s.io/metrics v0.17.6/go.mod h1:5AuIG+m+U5ga8DpqAUqQWBhGVyY485HfKpn471pmWrQ= k8s.io/test-infra v0.0.0-20181019233642-2e10a0bbe9b3/go.mod h1:2NzXB13Ji0nqpyublHeiPC4FZwU0TknfvyaaNfl/BTA= k8s.io/test-infra v0.0.0-20191212060232-70b0b49fe247/go.mod h1:d8SKryJBXAwfCFVL4wieRez47J2NOOAb9d029sWLseQ= k8s.io/test-infra v0.0.0-20200407001919-bc7f71ef65b8/go.mod h1:/WpJWcaDvuykB322WXP4kJbX8IpalOzuPxA62GpwkJk= @@ -1539,12 +1536,12 @@ k8s.io/utils v0.0.0-20200124190032-861946025e34/go.mod h1:sZAwmy6armz5eXlNoLmJcl knative.dev/caching v0.0.0-20190719140829-2032732871ff/go.mod h1:dHXFU6CGlLlbzaWc32g80cR92iuBSpsslDNBWI8C7eg= knative.dev/caching v0.0.0-20200116200605-67bca2c83dfa/go.mod h1:dHXFU6CGlLlbzaWc32g80cR92iuBSpsslDNBWI8C7eg= knative.dev/caching v0.0.0-20200606210318-787aec80f71c/go.mod h1:rWD+0zSqcE7L//jJyt866xtXsOi9hCdB0FoD4w2Rygg= -knative.dev/eventing v0.15.1-0.20200619221325-e8ca69f837c7 h1:VF5IdmrMUZXCdXQXBTi4YhlELqFmJFiKHJfgs0ojOOU= -knative.dev/eventing v0.15.1-0.20200619221325-e8ca69f837c7/go.mod h1:rBCHca+3Wl8Y5iaGmnNSjImZ8fIErj1dAS3WAbMSwuI= +knative.dev/eventing v0.15.1-0.20200623172931-13e513727e77 h1:9HtCPVGLCzAZQQDCOKd1J5LNHEkGhJ539t49+uAMc5M= +knative.dev/eventing v0.15.1-0.20200623172931-13e513727e77/go.mod h1:BpLzl5yzbGvu5/qN4N/+PgR5LzAmW/UAbgX0EvbpWFs= knative.dev/eventing-contrib v0.6.1-0.20190723221543-5ce18048c08b/go.mod h1:SnXZgSGgMSMLNFTwTnpaOH7hXDzTFtw0J8OmHflNx3g= knative.dev/eventing-contrib v0.11.2/go.mod h1:SnXZgSGgMSMLNFTwTnpaOH7hXDzTFtw0J8OmHflNx3g= -knative.dev/networking v0.0.0-20200619041525-1faac2ec5d38 h1:wxMxsdf8VI45h7ARlO1YOWjsielbBL3hl1FM2VCavUo= -knative.dev/networking v0.0.0-20200619041525-1faac2ec5d38/go.mod h1:ruIIg4U34uk2+LdS09aibF4ewgWn4PzwYcYCeyCY4K0= +knative.dev/networking v0.0.0-20200622163826-421cd312c651 h1:k0diNnPM6Bh7kvnHOGFOtt5VGYjD2ksjh8gh7J8TSTU= +knative.dev/networking v0.0.0-20200622163826-421cd312c651/go.mod h1:Jkh1EZcfkw1zcsrjLslk7/vsaAiG4LRyRP1l494UMEg= knative.dev/pkg v0.0.0-20191101194912-56c2594e4f11/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q= knative.dev/pkg v0.0.0-20191111150521-6d806b998379/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q= knative.dev/pkg v0.0.0-20200207155214-fef852970f43/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q= @@ -1558,15 +1555,14 @@ knative.dev/pkg v0.0.0-20200520073958-94316e20e860/go.mod h1:QgNZTxnwpB/oSpNcfnL knative.dev/pkg v0.0.0-20200603222317-b79e4a24ca50 h1:sbJMCCtOENPgfE5dUSwBUxZtJzhfqORhExyWFX7L0Fk= knative.dev/pkg v0.0.0-20200603222317-b79e4a24ca50/go.mod h1:8IfPj/lpuKHHg82xZCl2wuFZ3BM96To72sN1W8T9wjQ= knative.dev/pkg v0.0.0-20200611204322-2ddcfef739a2/go.mod h1:rA+FklsrVahwF4a+D63NyHJlzDoAFH81K4J5CYuE3bA= -knative.dev/pkg v0.0.0-20200618002824-96c250871fac h1:X8XHaSFsUIW2IJCIEQEzNfPbs/gGib3CUK/+lkZuoEo= -knative.dev/pkg v0.0.0-20200618002824-96c250871fac/go.mod h1:4ty6MSlNjZk5qBaGb3Gt4gopjMD4gRknfTABblcFpQ8= knative.dev/pkg v0.0.0-20200619020725-7df8fc5d7743/go.mod h1:DquzK0hsLDcg2q63Sn+CngAyRwv4cKMpt5F19YzBfb0= -knative.dev/pkg v0.0.0-20200619182625-b6a13e2894ee/go.mod h1:DquzK0hsLDcg2q63Sn+CngAyRwv4cKMpt5F19YzBfb0= -knative.dev/pkg v0.0.0-20200622015826-5e60b6f8633c h1:z2e+kANZR9haocnAqMUNGzjKq/BKbjIW8k80eoSZj3c= -knative.dev/pkg v0.0.0-20200622015826-5e60b6f8633c/go.mod h1:DquzK0hsLDcg2q63Sn+CngAyRwv4cKMpt5F19YzBfb0= +knative.dev/pkg v0.0.0-20200622135826-98f8a949a106/go.mod h1:DquzK0hsLDcg2q63Sn+CngAyRwv4cKMpt5F19YzBfb0= +knative.dev/pkg v0.0.0-20200623024526-fb0320d9287e/go.mod h1:DquzK0hsLDcg2q63Sn+CngAyRwv4cKMpt5F19YzBfb0= +knative.dev/pkg v0.0.0-20200623173527-5658d93fb07e h1:MhQNsqYZ5BuDyZT/Q5MQMTMYTmkLcwq6MY+gGvPkymY= +knative.dev/pkg v0.0.0-20200623173527-5658d93fb07e/go.mod h1:DquzK0hsLDcg2q63Sn+CngAyRwv4cKMpt5F19YzBfb0= knative.dev/sample-controller v0.0.0-20200510050845-bf7c19498b7e/go.mod h1:D2ZDLrR9Dq9LiiVN7TatzI7WMcEPgk1MHbbhgBKE6W8= -knative.dev/serving v0.15.1-0.20200621202726-40edbdd01f1c h1:oWD2gBcFmQ7vJW7pH7GBB92VLCclR2BFJtEGXOVISmI= -knative.dev/serving v0.15.1-0.20200621202726-40edbdd01f1c/go.mod h1:e+yhAR1xaRJNXMgy4v4r5cGEns3L9o6a+g3i2MFHNjg= +knative.dev/serving v0.15.1-0.20200623164334-a956ab8df9fa h1:SOcMk/2yVt1JbllJmcBIJ10AwkoHrh0gdvAIf/3yGsc= +knative.dev/serving v0.15.1-0.20200623164334-a956ab8df9fa/go.mod h1:38aDwyUPrO1AY1LvUjd3Y7tbXunGbVeisByMRR4bjPY= knative.dev/test-infra v0.0.0-20200407185800-1b88cb3b45a5/go.mod h1:xcdUkMJrLlBswIZqL5zCuBFOC22WIPMQoVX1L35i0vQ= knative.dev/test-infra v0.0.0-20200505052144-5ea2f705bb55/go.mod h1:WqF1Azka+FxPZ20keR2zCNtiQA1MP9ZB4BH4HuI+SIU= knative.dev/test-infra v0.0.0-20200508015845-8d7d46a46176/go.mod h1:aMif0KXL4g19YCYwsy4Ocjjz5xgPlseYV+B95Oo4JGE= @@ -1576,12 +1572,13 @@ knative.dev/test-infra v0.0.0-20200519015156-82551620b0a9/go.mod h1:A5b2OAXTOeHT knative.dev/test-infra v0.0.0-20200519161858-554a95a37986/go.mod h1:LeNa1Wvn47efeQUkpkn3XG7Fx9Ga+rhAP13SZyjaEGg= knative.dev/test-infra v0.0.0-20200522180958-6a0a9b9d893a/go.mod h1:n9eQkzmSNj8BiqNFl1lzoz68D09uMeJfyOjc132Gbik= knative.dev/test-infra v0.0.0-20200606045118-14ebc4a42974/go.mod h1://I6IZIF0QDgs5wotU243ZZ5cTpm6/GthayjUenBBc0= -knative.dev/test-infra v0.0.0-20200615231324-3a016f44102c/go.mod h1:+BfrTJpc++rH30gX/C0QY6NT2eYVzycll52uw6CrQnc= knative.dev/test-infra v0.0.0-20200617235125-6382dba95484 h1:5D1Fm6aA1T1QQXLb1HkJ5t8gB9pTkhLYak1CCqIP+pE= knative.dev/test-infra v0.0.0-20200617235125-6382dba95484/go.mod h1:+BfrTJpc++rH30gX/C0QY6NT2eYVzycll52uw6CrQnc= -knative.dev/test-infra v0.0.0-20200618184825-a7b2980a8884/go.mod h1:qeiTuhDKO/HHheqVfepbxy5/q+O9toSJW6CO/DgjxFY= knative.dev/test-infra v0.0.0-20200619200026-0b0587234302 h1:nGw173QprRCSZab6KT4uSj0GTp3WNRo0nfk9Lpo3F1I= knative.dev/test-infra v0.0.0-20200619200026-0b0587234302/go.mod h1:H8QEB2Y35+vAuVtDbn7QBD+NQr9zQbbxNiovCLNH7F4= +knative.dev/test-infra v0.0.0-20200623005026-1f7e5f05c52b/go.mod h1:H8QEB2Y35+vAuVtDbn7QBD+NQr9zQbbxNiovCLNH7F4= +knative.dev/test-infra v0.0.0-20200623145727-e9ff5263be06 h1:6LNkyjc5iPk+Q47wwixmc9CL/0GIL40wZWGlwHXTDRc= +knative.dev/test-infra v0.0.0-20200623145727-e9ff5263be06/go.mod h1:qKM6vO6hD6aa0ZYGDdyr5YiXPQMhbix1K8UWPUvVlIE= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= diff --git a/pkg/broker/eventutil/hops.go b/pkg/broker/eventutil/hops.go index 09c7c7bf09..bfac22ccb6 100644 --- a/pkg/broker/eventutil/hops.go +++ b/pkg/broker/eventutil/hops.go @@ -19,9 +19,9 @@ package eventutil import ( "context" - cetypes "github.com/cloudevents/sdk-go/pkg/cloudevents/types" "github.com/cloudevents/sdk-go/v2/binding" "github.com/cloudevents/sdk-go/v2/event" + cetypes "github.com/cloudevents/sdk-go/v2/types" "go.uber.org/zap" "knative.dev/eventing/pkg/logging" ) diff --git a/pkg/client/injection/reconciler/broker/v1beta1/broker/reconciler.go b/pkg/client/injection/reconciler/broker/v1beta1/broker/reconciler.go index 9a65810428..0a144e8079 100644 --- a/pkg/client/injection/reconciler/broker/v1beta1/broker/reconciler.go +++ b/pkg/client/injection/reconciler/broker/v1beta1/broker/reconciler.go @@ -236,10 +236,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/broker/v1beta1/trigger/reconciler.go b/pkg/client/injection/reconciler/broker/v1beta1/trigger/reconciler.go index c5cbd65048..daa9235258 100644 --- a/pkg/client/injection/reconciler/broker/v1beta1/trigger/reconciler.go +++ b/pkg/client/injection/reconciler/broker/v1beta1/trigger/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/reconciler.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/reconciler.go index 0dc988f32e..42baa4ddc3 100644 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/reconciler.go +++ b/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/reconciler.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/reconciler.go index 9bb2603eee..f830d31219 100644 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/reconciler.go +++ b/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/reconciler.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/reconciler.go index af85bc269a..0268d1dd72 100644 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/reconciler.go +++ b/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/reconciler.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/reconciler.go index d9ea685534..8a686a742f 100644 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/reconciler.go +++ b/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/reconciler.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/reconciler.go index 35fd177849..c6d4e32292 100644 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/reconciler.go +++ b/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/events/v1beta1/cloudauditlogssource/reconciler.go b/pkg/client/injection/reconciler/events/v1beta1/cloudauditlogssource/reconciler.go index a680ea494c..3a223148d3 100644 --- a/pkg/client/injection/reconciler/events/v1beta1/cloudauditlogssource/reconciler.go +++ b/pkg/client/injection/reconciler/events/v1beta1/cloudauditlogssource/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/events/v1beta1/cloudbuildsource/reconciler.go b/pkg/client/injection/reconciler/events/v1beta1/cloudbuildsource/reconciler.go index dce2547438..593364d264 100644 --- a/pkg/client/injection/reconciler/events/v1beta1/cloudbuildsource/reconciler.go +++ b/pkg/client/injection/reconciler/events/v1beta1/cloudbuildsource/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/events/v1beta1/cloudpubsubsource/reconciler.go b/pkg/client/injection/reconciler/events/v1beta1/cloudpubsubsource/reconciler.go index f639374529..d535195667 100644 --- a/pkg/client/injection/reconciler/events/v1beta1/cloudpubsubsource/reconciler.go +++ b/pkg/client/injection/reconciler/events/v1beta1/cloudpubsubsource/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/events/v1beta1/cloudschedulersource/reconciler.go b/pkg/client/injection/reconciler/events/v1beta1/cloudschedulersource/reconciler.go index ed5208a6cb..7367d6c8af 100644 --- a/pkg/client/injection/reconciler/events/v1beta1/cloudschedulersource/reconciler.go +++ b/pkg/client/injection/reconciler/events/v1beta1/cloudschedulersource/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/events/v1beta1/cloudstoragesource/reconciler.go b/pkg/client/injection/reconciler/events/v1beta1/cloudstoragesource/reconciler.go index 5168d853a7..b6b7c06e52 100644 --- a/pkg/client/injection/reconciler/events/v1beta1/cloudstoragesource/reconciler.go +++ b/pkg/client/injection/reconciler/events/v1beta1/cloudstoragesource/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/intevents/v1alpha1/brokercell/reconciler.go b/pkg/client/injection/reconciler/intevents/v1alpha1/brokercell/reconciler.go index bac50c286c..39d678c1b4 100644 --- a/pkg/client/injection/reconciler/intevents/v1alpha1/brokercell/reconciler.go +++ b/pkg/client/injection/reconciler/intevents/v1alpha1/brokercell/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/reconciler.go b/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/reconciler.go index a786be75c5..99de60781c 100644 --- a/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/reconciler.go +++ b/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/intevents/v1alpha1/topic/reconciler.go b/pkg/client/injection/reconciler/intevents/v1alpha1/topic/reconciler.go index 22187cd984..ffd903bd40 100644 --- a/pkg/client/injection/reconciler/intevents/v1alpha1/topic/reconciler.go +++ b/pkg/client/injection/reconciler/intevents/v1alpha1/topic/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/intevents/v1beta1/pullsubscription/reconciler.go b/pkg/client/injection/reconciler/intevents/v1beta1/pullsubscription/reconciler.go index 669458681f..5b4cddef55 100644 --- a/pkg/client/injection/reconciler/intevents/v1beta1/pullsubscription/reconciler.go +++ b/pkg/client/injection/reconciler/intevents/v1beta1/pullsubscription/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/intevents/v1beta1/topic/reconciler.go b/pkg/client/injection/reconciler/intevents/v1beta1/topic/reconciler.go index 332a9c9e37..9afbc11c30 100644 --- a/pkg/client/injection/reconciler/intevents/v1beta1/topic/reconciler.go +++ b/pkg/client/injection/reconciler/intevents/v1beta1/topic/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/messaging/v1alpha1/channel/reconciler.go b/pkg/client/injection/reconciler/messaging/v1alpha1/channel/reconciler.go index 3d4558b9e8..ee8b770a85 100644 --- a/pkg/client/injection/reconciler/messaging/v1alpha1/channel/reconciler.go +++ b/pkg/client/injection/reconciler/messaging/v1alpha1/channel/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/client/injection/reconciler/messaging/v1beta1/channel/reconciler.go b/pkg/client/injection/reconciler/messaging/v1beta1/channel/reconciler.go index fbc80b7b79..912f867427 100644 --- a/pkg/client/injection/reconciler/messaging/v1beta1/channel/reconciler.go +++ b/pkg/client/injection/reconciler/messaging/v1beta1/channel/reconciler.go @@ -225,10 +225,14 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { return fmt.Errorf("failed to set finalizers: %w", err) } + reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status // updates regardless of whether the reconciliation errored out. reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "ObserveKind")) diff --git a/pkg/pubsub/adapter/adapter.go b/pkg/pubsub/adapter/adapter.go index cc628d68f0..35be7f0e49 100644 --- a/pkg/pubsub/adapter/adapter.go +++ b/pkg/pubsub/adapter/adapter.go @@ -246,7 +246,7 @@ func (a *Adapter) sendMsg(ctx context.Context, address string, msg binding.Messa } func (a *Adapter) startSpan(ctx context.Context, event *cev2.Event) (context.Context, *trace.Span) { - spanName := tracing.SourceDestination(a.namespacedName) + spanName := tracing.SourceDestination(a.resourceGroup, a.namespacedName) // This receive adapter code is used both for Sources and Channels. // An ugly way to identify whether it was created from a Channel is to look at the resourceGroup. if a.resourceGroup == messaging.ChannelsResource.String() { diff --git a/pkg/pubsub/adapter/converters/pubsub_test.go b/pkg/pubsub/adapter/converters/pubsub_test.go index 069dfdabc1..253dcb3558 100644 --- a/pkg/pubsub/adapter/converters/pubsub_test.go +++ b/pkg/pubsub/adapter/converters/pubsub_test.go @@ -36,6 +36,7 @@ func TestConvertCloudPubSub(t *testing.T) { message *pubsub.Message wantEventFn func() *cev2.Event wantErr bool + wantInvalidContext bool }{{ name: "non alphanumeric attribute", message: &pubsub.Message{ @@ -62,13 +63,26 @@ func TestConvertCloudPubSub(t *testing.T) { wantEventFn: func() *cev2.Event { return pubSubCloudEvent(nil, "\"InRlc3QgZGF0YSI=\"") }, + }, { + name: "invalid context", + message: &pubsub.Message{ + ID: "id", + Data: []byte("\"test data\""), // Data passed in quotes for it to be marshalled properly + Attributes: map[string]string{}, + }, + wantInvalidContext: true, + wantErr: true, }} for _, test := range tests { t.Run(test.name, func(t *testing.T) { - ctx := WithProjectKey(context.Background(), "testproject") - ctx = WithTopicKey(ctx, "testtopic") - ctx = WithSubscriptionKey(ctx, "testsubscription") + ctx := context.Background() + // TODO add flags to test each of the keys + if !test.wantInvalidContext { + ctx = WithProjectKey(context.Background(), "testproject") + ctx = WithTopicKey(ctx, "testtopic") + ctx = WithSubscriptionKey(ctx, "testsubscription") + } gotEvent, err := NewPubSubConverter().Convert(ctx, test.message, CloudPubSub) if err != nil { diff --git a/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go b/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go index 273ec2bbf9..4db2b62d52 100644 --- a/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go +++ b/pkg/reconciler/intevents/pullsubscription/resources/receive_adapter_test.go @@ -23,11 +23,12 @@ import ( "github.com/google/go-cmp/cmp" duckv1beta1 "github.com/google/knative-gcp/pkg/apis/duck/v1beta1" + "github.com/google/knative-gcp/pkg/apis/intevents" "github.com/google/knative-gcp/pkg/apis/intevents/v1beta1" testingmetadata "github.com/google/knative-gcp/pkg/gclient/metadata/testing" "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" - "k8s.io/api/apps/v1" + v1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/pkg/apis" @@ -39,6 +40,9 @@ func TestMakeMinimumReceiveAdapter(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "testname", Namespace: "testnamespace", + Labels: map[string]string{ + intevents.SourceLabelKey: "my-source-name", + }, }, Spec: v1beta1.PullSubscriptionSpec{ PubSubSpec: duckv1beta1.PubSubSpec{ @@ -50,7 +54,8 @@ func TestMakeMinimumReceiveAdapter(t *testing.T) { }, Project: "eventing-name", }, - Topic: "topic", + Topic: "topic", + AdapterType: "source-adapter-type", }, } @@ -73,7 +78,7 @@ func TestMakeMinimumReceiveAdapter(t *testing.T) { want := &v1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Namespace: "testnamespace", - Name: "cre-ps-testname-", + Name: "cre-src-testname-", Annotations: nil, Labels: map[string]string{ "test-key1": "test-value1", @@ -121,8 +126,8 @@ func TestMakeMinimumReceiveAdapter(t *testing.T) { }, { Name: "TRANSFORMER_URI", }, { - Name: "ADAPTER_TYPE", - Value: string(converters.PubSubPull), + Name: "ADAPTER_TYPE", + Value: "source-adapter-type", }, { Name: "SEND_MODE", Value: "binary", diff --git a/pkg/tracing/attributes.go b/pkg/tracing/attributes.go index e590a31ee2..4808f5decc 100644 --- a/pkg/tracing/attributes.go +++ b/pkg/tracing/attributes.go @@ -18,6 +18,7 @@ package tracing import ( "fmt" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "knative.dev/eventing/pkg/tracing" ) @@ -34,6 +35,10 @@ func ChannelDestination(c types.NamespacedName) string { return fmt.Sprintf("channel:%s.%s", c.Name, c.Namespace) } -func SourceDestination(s types.NamespacedName) string { - return fmt.Sprintf("source:%s.%s", s.Name, s.Namespace) +func SourceDestination(resourceGroup string, src types.NamespacedName) string { + // resourceGroup is of the form .events.cloud.google.com, + // where resource can be for example cloudpubsubsources. + // We keep with the resource piece. + gr := schema.ParseGroupResource(resourceGroup) + return fmt.Sprintf("%s:%s.%s", gr.Resource, src.Name, src.Namespace) } diff --git a/third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/pkg/cloudevents/types/LICENSE b/third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/pkg/cloudevents/types/LICENSE deleted file mode 100644 index 261eeb9e9f..0000000000 --- a/third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/pkg/cloudevents/types/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/vendor/github.com/cloudevents/sdk-go/.gitignore b/vendor/github.com/cloudevents/sdk-go/.gitignore index d42a769153..2f9d9da00b 100644 --- a/vendor/github.com/cloudevents/sdk-go/.gitignore +++ b/vendor/github.com/cloudevents/sdk-go/.gitignore @@ -24,6 +24,6 @@ bazel-* # Others ## IDE-specific *.iml -test/benchmark/e2e/http/results/ +test/benchmark/http/results/ tmp/ diff --git a/vendor/github.com/cloudevents/sdk-go/README.md b/vendor/github.com/cloudevents/sdk-go/README.md index 6cfc8c3c33..4eb3e83b88 100644 --- a/vendor/github.com/cloudevents/sdk-go/README.md +++ b/vendor/github.com/cloudevents/sdk-go/README.md @@ -10,20 +10,6 @@ This SDK is still considered work in progress. -**With v1.1.0:** - -[Master](https://github.com/cloudevents/sdk-go/tree/master) will now be the base -of the effort for v2.0.0 of this SDK and will contain breaking changes or -missing libraries. - -Future work on v1.X.Y releases will branch off of -[release-1.y.z](https://github.com/cloudevents/sdk-go/tree/release-1.y.z). To -add a bugfix to a v1.X.Y release, please make a PR to that branch and we can do -releases as needed on the v1 SDK. No date for EOL on v1 support yet, that will -be determined by the progress on v2. - -The CloudEvents golang team is working hard to bring you v2.0.0 of the SDK. - **With v1.0.0:** The API that exists under [`pkg/cloudevents`](./pkg/cloudevents) will follow @@ -77,7 +63,7 @@ func main() { } ``` -Creating a minimal CloudEvent in version 1.0: +Creating a minimal CloudEvent in version 0.2: ```go event := cloudevents.NewEvent() @@ -87,12 +73,12 @@ event.SetSource("http://localhost:8080/") event.SetData(data) ``` -Sending a cloudevents.Event via the HTTP Transport with Binary v1.0 encoding: +Sending a cloudevents.Event via the HTTP Transport with Binary v0.2 encoding: ```go t, err := cloudevents.NewHTTPTransport( cloudevents.WithTarget("http://localhost:8080/"), - cloudevents.WithEncoding(cloudevents.HTTPBinaryV1), + cloudevents.WithEncoding(cloudevents.HTTPBinaryV02), ) if err != nil { panic("failed to create transport, " + err.Error()) diff --git a/vendor/github.com/cloudevents/sdk-go/alias.go b/vendor/github.com/cloudevents/sdk-go/alias.go index ef957d72a6..7bc4e54d39 100644 --- a/vendor/github.com/cloudevents/sdk-go/alias.go +++ b/vendor/github.com/cloudevents/sdk-go/alias.go @@ -95,12 +95,11 @@ var ( // Client Options - WithEventDefaulter = client.WithEventDefaulter - WithUUIDs = client.WithUUIDs - WithTimeNow = client.WithTimeNow - WithConverterFn = client.WithConverterFn - WithDataContentType = client.WithDataContentType - WithoutTracePropagation = client.WithoutTracePropagation + WithEventDefaulter = client.WithEventDefaulter + WithUUIDs = client.WithUUIDs + WithTimeNow = client.WithTimeNow + WithConverterFn = client.WithConverterFn + WithDataContentType = client.WithDataContentType // Event Creation @@ -143,11 +142,9 @@ var ( WithMiddleware = http.WithMiddleware WithLongPollTarget = http.WithLongPollTarget WithListener = http.WithListener - WithHTTPTransport = http.WithHTTPTransport // HTTP Context HTTPTransportContextFrom = http.TransportContextFrom ContextWithHeader = http.ContextWithHeader - SetContextHeaders = http.SetContextHeaders ) diff --git a/vendor/github.com/cloudevents/sdk-go/go.mod b/vendor/github.com/cloudevents/sdk-go/go.mod index 8e03d72f5f..71896ac8d6 100644 --- a/vendor/github.com/cloudevents/sdk-go/go.mod +++ b/vendor/github.com/cloudevents/sdk-go/go.mod @@ -7,29 +7,22 @@ require ( github.com/Azure/go-autorest/autorest v0.2.0 // indirect github.com/Azure/go-autorest/autorest/to v0.2.0 // indirect github.com/Azure/go-autorest/autorest/validation v0.1.0 // indirect - github.com/Shopify/sarama v1.19.0 github.com/fortytw2/leaktest v1.3.0 // indirect github.com/google/go-cmp v0.4.0 github.com/google/uuid v1.1.1 github.com/kelseyhightower/envconfig v1.4.0 - github.com/kr/pretty v0.2.0 // indirect - github.com/lightstep/tracecontext.go v0.0.0-20181129014701-1757c391b1ac github.com/nats-io/nats-server/v2 v2.1.2 github.com/nats-io/nats.go v1.9.1 github.com/pkg/errors v0.8.1 - github.com/stretchr/testify v1.4.0 + github.com/stretchr/testify v1.3.0 github.com/valyala/bytebufferpool v1.0.0 go.opencensus.io v0.22.0 go.uber.org/atomic v1.4.0 // indirect go.uber.org/multierr v1.1.0 // indirect go.uber.org/zap v1.10.0 - golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 // indirect - golang.org/x/net v0.0.0-20200202094626-16171245cfb2 // indirect golang.org/x/sync v0.0.0-20190423024810-112230192c58 google.golang.org/api v0.15.0 google.golang.org/grpc v1.26.0 - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect - gopkg.in/yaml.v2 v2.2.8 // indirect pack.ag/amqp v0.11.0 ) diff --git a/vendor/github.com/cloudevents/sdk-go/go.sum b/vendor/github.com/cloudevents/sdk-go/go.sum index 80b4c71a1c..c4b4dce970 100644 --- a/vendor/github.com/cloudevents/sdk-go/go.sum +++ b/vendor/github.com/cloudevents/sdk-go/go.sum @@ -26,9 +26,7 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L github.com/Azure/go-autorest/tracing v0.1.0 h1:TRBxC5Pj/fIuh4Qob0ZpkggbfT8RC0SubHbpV3p4/Vc= github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Shopify/sarama v1.19.0 h1:9oksLxC6uxVPHPVYUmq6xhr1BOF/hHobWH2UzO67z1s= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -45,11 +43,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/eapache/go-resiliency v1.1.0 h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -72,7 +67,6 @@ github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -95,7 +89,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= @@ -104,15 +97,9 @@ github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lightstep/tracecontext.go v0.0.0-20181129014701-1757c391b1ac h1:+2b6iGRJe3hvV/yVXrd41yVEjxuFHxasJqDhkIjS4gk= -github.com/lightstep/tracecontext.go v0.0.0-20181129014701-1757c391b1ac/go.mod h1:Frd2bnT3w5FB5q49ENTfVlztJES+1k/7lyWX2+9gq/M= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -129,12 +116,9 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= @@ -161,7 +145,6 @@ github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nL github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -170,8 +153,6 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -190,8 +171,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90Pveol golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 h1:+ELyKg6m8UBf0nPFSqD0mi7zUfwPyXo23HNjMnXPz7w= -golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -212,8 +191,6 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= @@ -281,21 +258,12 @@ google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/client/client.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/client/client.go index 209eb8f77a..a5e5c27a1d 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/client/client.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/client/client.go @@ -6,11 +6,9 @@ import ( "sync" "github.com/cloudevents/sdk-go/pkg/cloudevents" - "github.com/cloudevents/sdk-go/pkg/cloudevents/extensions" "github.com/cloudevents/sdk-go/pkg/cloudevents/observability" "github.com/cloudevents/sdk-go/pkg/cloudevents/transport" "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http" - "go.opencensus.io/trace" ) // Client interface defines the runtime contract the CloudEvents client supports. @@ -80,8 +78,6 @@ type ceClient struct { receiverMu sync.Mutex eventDefaulterFns []EventDefaulter - - disableTracePropagation bool } // Send transmits the provided event on a preconfigured Transport. @@ -90,13 +86,6 @@ type ceClient struct { // error. func (c *ceClient) Send(ctx context.Context, event cloudevents.Event) (context.Context, *cloudevents.Event, error) { ctx, r := observability.NewReporter(ctx, reportSend) - - ctx, span := trace.StartSpan(ctx, clientSpanName, trace.WithSpanKind(trace.SpanKindClient)) - defer span.End() - if span.IsRecordingEvents() { - span.AddAttributes(eventTraceAttributes(event.Context)...) - } - rctx, resp, err := c.obsSend(ctx, event) if err != nil { r.Error() @@ -118,16 +107,6 @@ func (c *ceClient) obsSend(ctx context.Context, event cloudevents.Event) (contex } } - // Set distributed tracing extension. - if !c.disableTracePropagation { - if span := trace.FromContext(ctx); span != nil { - event.Context = event.Context.Clone() - if err := extensions.FromSpanContext(span.SpanContext()).AddTracingAttributes(event.Context); err != nil { - return ctx, nil, fmt.Errorf("error setting distributed tracing extension: %w", err) - } - } - } - // Validate the event conforms to the CloudEvents Spec. if err := event.Validate(); err != nil { return ctx, nil, err @@ -139,21 +118,6 @@ func (c *ceClient) obsSend(ctx context.Context, event cloudevents.Event) (contex // Receive is called from from the transport on event delivery. func (c *ceClient) Receive(ctx context.Context, event cloudevents.Event, resp *cloudevents.EventResponse) error { ctx, r := observability.NewReporter(ctx, reportReceive) - - var span *trace.Span - if !c.transport.HasTracePropagation() { - if ext, ok := extensions.GetDistributedTracingExtension(event); ok { - ctx, span = ext.StartChildSpan(ctx, clientSpanName, trace.WithSpanKind(trace.SpanKindServer)) - } - } - if span == nil { - ctx, span = trace.StartSpan(ctx, clientSpanName, trace.WithSpanKind(trace.SpanKindServer)) - } - defer span.End() - if span.IsRecordingEvents() { - span.AddAttributes(eventTraceAttributes(event.Context)...) - } - err := c.obsReceive(ctx, event, resp) if err != nil { r.Error() @@ -165,7 +129,13 @@ func (c *ceClient) Receive(ctx context.Context, event cloudevents.Event, resp *c func (c *ceClient) obsReceive(ctx context.Context, event cloudevents.Event, resp *cloudevents.EventResponse) error { if c.fn != nil { + ctx, rFn := observability.NewReporter(ctx, reportReceiveFn) err := c.fn.invoke(ctx, event, resp) + if err != nil { + rFn.Error() + } else { + rFn.OK() + } // Apply the defaulter chain to the outgoing event. if err == nil && resp != nil && resp.Event != nil && len(c.eventDefaulterFns) > 0 { diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/client/observability.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/client/observability.go index 9b67627c26..b844c19a86 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/client/observability.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/client/observability.go @@ -1,11 +1,9 @@ package client import ( - "github.com/cloudevents/sdk-go/pkg/cloudevents" "github.com/cloudevents/sdk-go/pkg/cloudevents/observability" "go.opencensus.io/stats" "go.opencensus.io/stats/view" - "go.opencensus.io/trace" ) var ( @@ -31,18 +29,25 @@ type observed int32 var _ observability.Observable = observed(0) const ( - clientSpanName = "cloudevents.client" - - specversionAttr = "cloudevents.specversion" - typeAttr = "cloudevents.type" - sourceAttr = "cloudevents.source" - subjectAttr = "cloudevents.subject" - datacontenttypeAttr = "cloudevents.datacontenttype" - reportSend observed = iota reportReceive + reportReceiveFn ) +// TraceName implements Observable.TraceName +func (o observed) TraceName() string { + switch o { + case reportSend: + return "client/send" + case reportReceive: + return "client/receive" + case reportReceiveFn: + return "client/receive/fn" + default: + return "client/unknown" + } +} + // MethodName implements Observable.MethodName func (o observed) MethodName() string { switch o { @@ -50,6 +55,8 @@ func (o observed) MethodName() string { return "send" case reportReceive: return "receive" + case reportReceiveFn: + return "receive/fn" default: return "unknown" } @@ -59,18 +66,3 @@ func (o observed) MethodName() string { func (o observed) LatencyMs() *stats.Float64Measure { return LatencyMs } - -func eventTraceAttributes(e cloudevents.EventContextReader) []trace.Attribute { - as := []trace.Attribute{ - trace.StringAttribute(specversionAttr, e.GetSpecVersion()), - trace.StringAttribute(typeAttr, e.GetType()), - trace.StringAttribute(sourceAttr, e.GetSource()), - } - if sub := e.GetSubject(); sub != "" { - as = append(as, trace.StringAttribute(subjectAttr, sub)) - } - if dct := e.GetDataContentType(); dct != "" { - as = append(as, trace.StringAttribute(datacontenttypeAttr, dct)) - } - return as -} diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/client/options.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/client/options.go index a9364f6ad7..bb2eff9cc7 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/client/options.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/client/options.go @@ -61,12 +61,3 @@ func WithConverterFn(fn ConvertFn) Option { return nil } } - -// WithoutTracePropagation disables automatic trace propagation via -// the distributed tracing extension. -func WithoutTracePropagation() Option { - return func(c *ceClient) error { - c.disableTracePropagation = true - return nil - } -} diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec/json/observability.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec/json/observability.go index 1d5c3fee74..d38a4b7d25 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec/json/observability.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec/json/observability.go @@ -33,6 +33,18 @@ const ( reportDecode ) +// TraceName implements Observable.TraceName +func (o observed) TraceName() string { + switch o { + case reportEncode: + return "datacodec/json/encode" + case reportDecode: + return "datacodec/json/decode" + default: + return "datacodec/json/unknown" + } +} + // MethodName implements Observable.MethodName func (o observed) MethodName() string { switch o { diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec/observability.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec/observability.go index a8daf5ea60..a51e05eb9f 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec/observability.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec/observability.go @@ -33,6 +33,18 @@ const ( reportDecode ) +// TraceName implements Observable.TraceName +func (o observed) TraceName() string { + switch o { + case reportEncode: + return "datacodec/encode" + case reportDecode: + return "datacodec/decode" + default: + return "datacodec/unknown" + } +} + // MethodName implements Observable.MethodName func (o observed) MethodName() string { switch o { diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec/xml/observability.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec/xml/observability.go index 32b3a5ff99..31b0bb2699 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec/xml/observability.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec/xml/observability.go @@ -33,6 +33,18 @@ const ( reportDecode ) +// TraceName implements Observable.TraceName +func (o observed) TraceName() string { + switch o { + case reportEncode: + return "datacodec/xml/encode" + case reportDecode: + return "datacodec/xml/decode" + default: + return "datacodec/xml/unknown" + } +} + // MethodName implements Observable.MethodName func (o observed) MethodName() string { switch o { diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/event.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/event.go index 2f605fd3c6..8e03476934 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/event.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/event.go @@ -34,7 +34,7 @@ func (e *Event) fieldOK(field string) { } // New returns a new Event, an optional version can be passed to change the -// default spec version from 1.0 to the provided version. +// default spec version from 0.2 to the provided version. func New(version ...string) Event { specVersion := defaultEventVersion // TODO: should there be a default? or set a default? if len(version) >= 1 { diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/event_observability.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/event_observability.go index bf1c5c5d7c..bce63f5c60 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/event_observability.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/event_observability.go @@ -38,6 +38,18 @@ const ( reportUnmarshal ) +// TraceName implements Observable.TraceName +func (o observed) TraceName() string { + switch o { + case reportMarshal: + return "cloudevents/event/marshaljson" + case reportUnmarshal: + return "cloudevents/event/unmarshaljson" + default: + return "cloudevents/event/unknwown" + } +} + // MethodName implements Observable.MethodName func (o observed) MethodName() string { switch o { @@ -66,6 +78,11 @@ type eventJSONObserved struct { // Adheres to Observable var _ observability.Observable = (*eventJSONObserved)(nil) +// TraceName implements Observable.TraceName +func (c eventJSONObserved) TraceName() string { + return fmt.Sprintf("%s/%s", c.o.TraceName(), c.v) +} + // MethodName implements Observable.MethodName func (c eventJSONObserved) MethodName() string { return fmt.Sprintf("%s/%s", c.o.MethodName(), c.v) diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v01.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v01.go index f48459cdf5..0b01823beb 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v01.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v01.go @@ -76,21 +76,7 @@ func (ec *EventContextV01) SetExtension(name string, value interface{}) error { // Clone implements EventContextConverter.Clone func (ec EventContextV01) Clone() EventContext { - ev01 := ec.AsV01() - ev01.Extensions = ev01.cloneExtensions() - return ev01 -} - -func (ec *EventContextV01) cloneExtensions() map[string]interface{} { - old := ec.Extensions - if old == nil { - return nil - } - new := make(map[string]interface{}, len(ec.Extensions)) - for k, v := range old { - new[k] = v - } - return new + return ec.AsV01() } // AsV01 implements EventContextConverter.AsV01 diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v02.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v02.go index 7b936bd81a..3dde8a19b1 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v02.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v02.go @@ -85,21 +85,7 @@ func (ec *EventContextV02) SetExtension(name string, value interface{}) error { // Clone implements EventContextConverter.Clone func (ec EventContextV02) Clone() EventContext { - ec02 := ec.AsV02() - ec02.Extensions = ec02.cloneExtensions() - return ec02 -} - -func (ec *EventContextV02) cloneExtensions() map[string]interface{} { - old := ec.Extensions - if old == nil { - return nil - } - new := make(map[string]interface{}, len(ec.Extensions)) - for k, v := range old { - new[k] = v - } - return new + return ec.AsV02() } // AsV01 implements EventContextConverter.AsV01 diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v03.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v03.go index 6fc776539e..2e714d1876 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v03.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v03.go @@ -94,21 +94,7 @@ func (ec *EventContextV03) SetExtension(name string, value interface{}) error { // Clone implements EventContextConverter.Clone func (ec EventContextV03) Clone() EventContext { - ec03 := ec.AsV03() - ec03.Extensions = ec03.cloneExtensions() - return ec03 -} - -func (ec *EventContextV03) cloneExtensions() map[string]interface{} { - old := ec.Extensions - if old == nil { - return nil - } - new := make(map[string]interface{}, len(ec.Extensions)) - for k, v := range old { - new[k] = v - } - return new + return ec.AsV03() } // AsV01 implements EventContextConverter.AsV01 diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v1.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v1.go index 320f47e0d9..8bb8cb41bd 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v1.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/eventcontext_v1.go @@ -97,21 +97,7 @@ func (ec *EventContextV1) SetExtension(name string, value interface{}) error { // Clone implements EventContextConverter.Clone func (ec EventContextV1) Clone() EventContext { - ec1 := ec.AsV1() - ec1.Extensions = ec1.cloneExtensions() - return ec1 -} - -func (ec *EventContextV1) cloneExtensions() map[string]interface{} { - old := ec.Extensions - if old == nil { - return nil - } - new := make(map[string]interface{}, len(ec.Extensions)) - for k, v := range old { - new[k] = v - } - return new + return ec.AsV1() } // AsV01 implements EventContextConverter.AsV01 diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/extensions/distributed_tracing_extension.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/extensions/distributed_tracing_extension.go deleted file mode 100644 index 2015c5449f..0000000000 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/extensions/distributed_tracing_extension.go +++ /dev/null @@ -1,135 +0,0 @@ -package extensions - -import ( - "context" - "reflect" - "strings" - - "github.com/cloudevents/sdk-go/pkg/cloudevents" - "github.com/cloudevents/sdk-go/pkg/cloudevents/types" - "github.com/lightstep/tracecontext.go/traceparent" - "github.com/lightstep/tracecontext.go/tracestate" - "go.opencensus.io/trace" - octs "go.opencensus.io/trace/tracestate" -) - -const ( - TraceParentExtension = "traceparent" - TraceStateExtension = "tracestate" -) - -// EventTracer interface allows setting extension for cloudevents context. -type EventTracer interface { - SetExtension(k string, v interface{}) error -} - -// DistributedTracingExtension represents the extension for cloudevents context -type DistributedTracingExtension struct { - TraceParent string `json:"traceparent"` - TraceState string `json:"tracestate"` -} - -// AddTracingAttributes adds the tracing attributes traceparent and tracestate to the cloudevents context -func (d DistributedTracingExtension) AddTracingAttributes(ec EventTracer) error { - if d.TraceParent != "" { - value := reflect.ValueOf(d) - typeOf := value.Type() - - for i := 0; i < value.NumField(); i++ { - k := strings.ToLower(typeOf.Field(i).Name) - v := value.Field(i).Interface() - if k == TraceStateExtension && v == "" { - continue - } - if err := ec.SetExtension(k, v); err != nil { - return err - } - } - } - return nil -} - -func GetDistributedTracingExtension(event cloudevents.Event) (DistributedTracingExtension, bool) { - if tp, ok := event.Extensions()[TraceParentExtension]; ok { - if tpStr, err := types.ToString(tp); err == nil { - var tsStr string - if ts, ok := event.Extensions()[TraceStateExtension]; ok { - tsStr, _ = types.ToString(ts) - } - return DistributedTracingExtension{TraceParent: tpStr, TraceState: tsStr}, true - } - } - return DistributedTracingExtension{}, false -} - -// FromSpanContext populates DistributedTracingExtension from a SpanContext. -func FromSpanContext(sc trace.SpanContext) DistributedTracingExtension { - tp := traceparent.TraceParent{ - TraceID: sc.TraceID, - SpanID: sc.SpanID, - Flags: traceparent.Flags{ - Recorded: sc.IsSampled(), - }, - } - - entries := make([]string, 0, len(sc.Tracestate.Entries())) - for _, entry := range sc.Tracestate.Entries() { - entries = append(entries, strings.Join([]string{entry.Key, entry.Value}, "=")) - } - - return DistributedTracingExtension{ - TraceParent: tp.String(), - TraceState: strings.Join(entries, ","), - } -} - -// ToSpanContext creates a SpanContext from a DistributedTracingExtension instance. -func (d DistributedTracingExtension) ToSpanContext() (trace.SpanContext, error) { - tp, err := traceparent.ParseString(d.TraceParent) - if err != nil { - return trace.SpanContext{}, err - } - sc := trace.SpanContext{ - TraceID: tp.TraceID, - SpanID: tp.SpanID, - } - if tp.Flags.Recorded { - sc.TraceOptions |= 1 - } - - if ts, err := tracestate.ParseString(d.TraceState); err == nil { - entries := make([]octs.Entry, 0, len(ts)) - for _, member := range ts { - var key string - if member.Tenant != "" { - // Due to github.com/lightstep/tracecontext.go/issues/6, - // the meaning of Vendor and Tenant are swapped here. - key = member.Vendor + "@" + member.Tenant - } else { - key = member.Vendor - } - entries = append(entries, octs.Entry{Key: key, Value: member.Value}) - } - sc.Tracestate, _ = octs.New(nil, entries...) - } - - return sc, nil -} - -func (d DistributedTracingExtension) StartChildSpan(ctx context.Context, name string, opts ...trace.StartOption) (context.Context, *trace.Span) { - if sc, err := d.ToSpanContext(); err == nil { - tSpan := trace.FromContext(ctx) - ctx, span := trace.StartSpanWithRemoteParent(ctx, name, sc, opts...) - if tSpan != nil { - // Add link to the previous in-process trace. - tsc := tSpan.SpanContext() - span.AddLink(trace.Link{ - TraceID: tsc.TraceID, - SpanID: tsc.SpanID, - Type: trace.LinkTypeParent, - }) - } - return ctx, span - } - return ctx, nil -} diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/observability/observer.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/observability/observer.go index b27ffa9735..76e7b12fda 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/observability/observer.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/observability/observer.go @@ -7,18 +7,20 @@ import ( "go.opencensus.io/stats" "go.opencensus.io/tag" + "go.opencensus.io/trace" ) // Observable represents the the customization used by the Reporter for a given // measurement and trace for a single method. type Observable interface { + TraceName() string MethodName() string LatencyMs() *stats.Float64Measure } -// Reporter represents a running latency counter. When Error or OK are -// called, the latency is calculated. Error or OK are only allowed to -// be called once. +// Reporter represents a running latency counter and trace span. When Error or +// OK are called, the latency is calculated and the trace space is ended. Error +// or OK are only allowed to be called once. type Reporter interface { Error() OK() @@ -26,6 +28,7 @@ type Reporter interface { type reporter struct { ctx context.Context + span *trace.Span on Observable start time.Time once sync.Once @@ -36,14 +39,30 @@ func LatencyTags() []tag.Key { return []tag.Key{KeyMethod, KeyResult} } -// Deprecated. Tracing is always enabled. -func EnableTracing(enabled bool) {} +var ( + // Tracing is disabled by default. It is very useful for profiling an + // application. + tracingEnabled = false +) + +// EnableTracing allows control over if tracing is enabled for the sdk. +// Default is false. This applies to all of the +// `github.com/cloudevents/sdk-go/...` package. +func EnableTracing(enabled bool) { + tracingEnabled = enabled +} -// NewReporter creates and returns a reporter wrapping the provided Observable. +// NewReporter creates and returns a reporter wrapping the provided Observable, +// and injects a trace span into the context. func NewReporter(ctx context.Context, on Observable) (context.Context, Reporter) { + var span *trace.Span + if tracingEnabled { + ctx, span = trace.StartSpan(ctx, on.TraceName()) + } r := &reporter{ ctx: ctx, on: on, + span: span, start: time.Now(), } r.tagMethod() @@ -61,6 +80,9 @@ func (r *reporter) tagMethod() { func (r *reporter) record() { ms := float64(time.Since(r.start) / time.Millisecond) stats.Record(r.ctx, r.on.LatencyMs().M(ms)) + if r.span != nil { + r.span.End() + } } // Error records the result as an error. diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/codec.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/codec.go index 05b8cdb156..889c228dde 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/codec.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/codec.go @@ -37,6 +37,8 @@ var _ transport.Codec = (*Codec)(nil) func (c *Codec) loadCodec(encoding Encoding) (transport.Codec, error) { switch encoding { + case Default: + fallthrough case BinaryV01, StructuredV01: c._v01.Do(func() { c.v01 = &CodecV01{DefaultEncoding: c.Encoding} @@ -52,7 +54,7 @@ func (c *Codec) loadCodec(encoding Encoding) (transport.Codec, error) { c.v03 = &CodecV03{DefaultEncoding: c.Encoding} }) return c.v03, nil - case BinaryV1, StructuredV1, BatchedV1, Default: + case BinaryV1, StructuredV1, BatchedV1: c._v1.Do(func() { c.v1 = &CodecV1{DefaultEncoding: c.Encoding} }) diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/context.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/context.go index 8e3c7b44e1..cf8b8510d7 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/context.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/context.go @@ -180,11 +180,6 @@ func HeaderFrom(ctx context.Context) http.Header { return ch } -// SetContextHeader sets the context's headers replacing any headers currently in context. -func SetContextHeaders(ctx context.Context, headers http.Header) context.Context { - return context.WithValue(ctx, headerKey, headers) -} - // Opaque key type used to store long poll target. type longPollTargetKeyType struct{} diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/observability.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/observability.go index 4017157201..1da56dc2ad 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/observability.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/observability.go @@ -41,6 +41,24 @@ const ( reportDecode ) +// TraceName implements Observable.TraceName +func (o observed) TraceName() string { + switch o { + case reportSend: + return "transport/http/send" + case reportReceive: + return "transport/http/receive" + case reportServeHTTP: + return "transport/http/servehttp" + case reportEncode: + return "transport/http/encode" + case reportDecode: + return "transport/http/decode" + default: + return "transport/http/unknown" + } +} + // MethodName implements Observable.MethodName func (o observed) MethodName() string { switch o { @@ -75,6 +93,11 @@ type CodecObserved struct { // Adheres to Observable var _ observability.Observable = (*CodecObserved)(nil) +// TraceName implements Observable.TraceName +func (c CodecObserved) TraceName() string { + return fmt.Sprintf("%s/%s", c.o.TraceName(), c.c) +} + // MethodName implements Observable.MethodName func (c CodecObserved) MethodName() string { return fmt.Sprintf("%s/%s", c.o.MethodName(), c.c) diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/options.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/options.go index fde7598b0e..0276157fcc 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/options.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/options.go @@ -40,8 +40,8 @@ func WithTarget(targetUrl string) Option { } } -// WithMethod sets the HTTP verb (GET, POST, PUT, etc.) to use -// when using an HTTP request. +// WithMethod sets the outbound recipient of cloudevents when using an HTTP +// request. func WithMethod(method string) Option { return func(t *Transport) error { if t == nil { @@ -264,11 +264,3 @@ func WithLongPollTarget(targetUrl string) Option { return fmt.Errorf("http long poll target option was empty string") } } - -// WithHTTPTransport sets the HTTP client transport. -func WithHTTPTransport(httpTransport nethttp.RoundTripper) Option { - return func(t *Transport) error { - t.transport = httpTransport - return nil - } -} diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/transport.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/transport.go index 2c79e56729..f68abb1ad4 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/transport.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http/transport.go @@ -13,8 +13,6 @@ import ( "sync" "time" - "go.opencensus.io/plugin/ochttp" - "go.opencensus.io/plugin/ochttp/propagation/tracecontext" "go.uber.org/zap" "github.com/cloudevents/sdk-go/pkg/cloudevents" @@ -48,10 +46,9 @@ type Transport struct { // Sending - // Deprecated - setting http client will override use of the - // HTTP transport set with WithHTTPTransport. + // Client is the http client that will be used to send requests. + // If nil, the Transport will create a one. Client *http.Client - // Req is the base http request that is used for http.Do. // Only .Method, .URL, .Close, and .Header is considered. // If not set, Req.Method defaults to POST. @@ -93,10 +90,6 @@ type Transport struct { reMu sync.Mutex middleware []Middleware - - // transport is the http client transport that will be used to send requests. - // If nil, the default transport will be used. - transport http.RoundTripper } func New(opts ...Option) (*Transport, error) { @@ -108,12 +101,6 @@ func New(opts ...Option) (*Transport, error) { if err := t.applyOptions(opts...); err != nil { return nil, err } - t.transport = &ochttp.Transport{ - Base: t.transport, - Propagation: &tracecontext.HTTPFormat{}, - NewClientTrace: ochttp.NewSpanAnnotatingClientTrace, - FormatSpanName: formatSpanName, - } return t, nil } @@ -181,6 +168,14 @@ func (t *Transport) Send(ctx context.Context, event cloudevents.Event) (context. } func (t *Transport) obsSend(ctx context.Context, event cloudevents.Event) (context.Context, *cloudevents.Event, error) { + if t.Client == nil { + t.crMu.Lock() + if t.Client == nil { + t.Client = &http.Client{} + } + t.crMu.Unlock() + } + req := http.Request{ Header: HeaderFrom(ctx), } @@ -208,11 +203,7 @@ func (t *Transport) obsSend(ctx context.Context, event cloudevents.Event) (conte if m, ok := msg.(*Message); ok { m.ToRequest(&req) - client := t.Client - if client == nil { - client = &http.Client{Transport: t.transport} - } - return httpDo(ctx, client, &req, func(resp *http.Response, err error) (context.Context, *cloudevents.Event, error) { + return httpDo(ctx, t.Client, &req, func(resp *http.Response, err error) (context.Context, *cloudevents.Event, error) { rctx := WithTransportContext(ctx, NewTransportContextFromResponse(resp)) if err != nil { return rctx, nil, err @@ -329,12 +320,8 @@ func (t *Transport) StartReceiver(ctx context.Context) error { } t.server = &http.Server{ - Addr: addr.String(), - Handler: &ochttp.Handler{ - Propagation: &tracecontext.HTTPFormat{}, - Handler: attachMiddleware(t.Handler, t.middleware), - FormatSpanName: formatSpanName, - }, + Addr: addr.String(), + Handler: attachMiddleware(t.Handler, t.middleware), } // Shutdown @@ -366,11 +353,6 @@ func (t *Transport) StartReceiver(ctx context.Context) error { } } -// HasTracePropagation implements Transport.HasTracePropagation -func (t *Transport) HasTracePropagation() bool { - return true -} - func (t *Transport) longPollStart(ctx context.Context) error { logger := cecontext.LoggerFrom(ctx) logger.Info("starting long poll receiver") @@ -474,10 +456,6 @@ func attachMiddleware(h http.Handler, middleware []Middleware) http.Handler { return h } -func formatSpanName(r *http.Request) string { - return "cloudevents.http." + r.URL.Path -} - type eventError struct { ctx context.Context event *cloudevents.Event diff --git a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/transport.go b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/transport.go index ba7979da67..a08d5a12e5 100644 --- a/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/transport.go +++ b/vendor/github.com/cloudevents/sdk-go/pkg/cloudevents/transport/transport.go @@ -19,11 +19,6 @@ type Transport interface { SetConverter(Converter) // HasConverter is true when a non-nil converter has been set. HasConverter() bool - // HasTracePropagation is true when the transport implements - // in-band trace propagation. When false, the client receiver - // will propagate trace context from distributed tracing - // extension attributes when available. - HasTracePropagation() bool } // Receiver is an interface to define how a transport will invoke a listener diff --git a/vendor/gopkg.in/yaml.v3/.travis.yml b/vendor/gopkg.in/yaml.v3/.travis.yml index fc88f9bbfc..1bc5c1cd20 100644 --- a/vendor/gopkg.in/yaml.v3/.travis.yml +++ b/vendor/gopkg.in/yaml.v3/.travis.yml @@ -12,4 +12,4 @@ go: - "1.12" - tip -go_import_path: gopkg.in/yaml.v2 +go_import_path: gopkg.in/yaml.v3 diff --git a/vendor/gopkg.in/yaml.v3/decode.go b/vendor/gopkg.in/yaml.v3/decode.go index 038b08b918..be63169b71 100644 --- a/vendor/gopkg.in/yaml.v3/decode.go +++ b/vendor/gopkg.in/yaml.v3/decode.go @@ -350,7 +350,12 @@ func (d *decoder) terror(n *Node, tag string, out reflect.Value) { } func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) { - if err := u.UnmarshalYAML(n); err != nil { + err := u.UnmarshalYAML(n) + if e, ok := err.(*TypeError); ok { + d.terrors = append(d.terrors, e.Errors...) + return false + } + if err != nil { fail(err) } return true @@ -434,12 +439,41 @@ func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field ref return v } +const ( + // 400,000 decode operations is ~500kb of dense object declarations, or + // ~5kb of dense object declarations with 10000% alias expansion + alias_ratio_range_low = 400000 + + // 4,000,000 decode operations is ~5MB of dense object declarations, or + // ~4.5MB of dense object declarations with 10% alias expansion + alias_ratio_range_high = 4000000 + + // alias_ratio_range is the range over which we scale allowed alias ratios + alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low) +) + +func allowedAliasRatio(decodeCount int) float64 { + switch { + case decodeCount <= alias_ratio_range_low: + // allow 99% to come from alias expansion for small-to-medium documents + return 0.99 + case decodeCount >= alias_ratio_range_high: + // allow 10% to come from alias expansion for very large documents + return 0.10 + default: + // scale smoothly from 99% down to 10% over the range. + // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range. + // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps). + return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range) + } +} + func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) { d.decodeCount++ if d.aliasDepth > 0 { d.aliasCount++ } - if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > 0.99 { + if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) { failf("document contains excessive aliasing") } if out.Type() == nodeType { @@ -790,7 +824,7 @@ func isStringMap(n *Node) bool { return false } l := len(n.Content) - for i := 0; i < l; i++ { + for i := 0; i < l; i += 2 { if n.Content[i].ShortTag() != strTag { return false } diff --git a/vendor/gopkg.in/yaml.v3/emitterc.go b/vendor/gopkg.in/yaml.v3/emitterc.go index 808c34b32d..ab2a066194 100644 --- a/vendor/gopkg.in/yaml.v3/emitterc.go +++ b/vendor/gopkg.in/yaml.v3/emitterc.go @@ -341,6 +341,7 @@ func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t emitter.whitespace = true emitter.indention = true emitter.space_above = true + emitter.foot_indent = -1 if emitter.encoding != yaml_UTF8_ENCODING { if !yaml_emitter_write_bom(emitter) { @@ -498,16 +499,14 @@ func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t if event.typ != yaml_DOCUMENT_END_EVENT { return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END") } - if !yaml_emitter_write_indent(emitter) { + // [Go] Force document foot separation. + emitter.foot_indent = 0 + if !yaml_emitter_process_foot_comment(emitter) { return false } - if len(emitter.foot_comment) > 0 { - if !put_break(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } + emitter.foot_indent = -1 + if !yaml_emitter_write_indent(emitter) { + return false } if !event.implicit { // [Go] Allocate the slice elsewhere. @@ -728,7 +727,7 @@ func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_ if first { // [Go] The original logic here would not indent the sequence when inside a mapping. // In Go we always indent it, but take the sequence indicator out of the indentation. - indentless := emitter.best_indent == 2 && emitter.mapping_context && !emitter.indention + indentless := emitter.best_indent == 2 && emitter.mapping_context && (emitter.column == 0 || !emitter.indention) original := emitter.indent if !yaml_emitter_increase_indent(emitter, false, indentless) { return false @@ -1097,27 +1096,15 @@ func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool { return false } emitter.tail_comment = emitter.tail_comment[:0] + emitter.foot_indent = emitter.indent + if emitter.foot_indent < 0 { + emitter.foot_indent = 0 + } } if len(emitter.head_comment) == 0 { return true } - - space_above := emitter.space_above - if !emitter.indention { - if !put_break(emitter) { - return false - } - } - if !space_above && - emitter.state != yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE && - emitter.state != yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE && - emitter.state != yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE && - emitter.state != yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE { - if !put_break(emitter) { - return false - } - } if !yaml_emitter_write_indent(emitter) { return false } @@ -1157,6 +1144,10 @@ func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool { return false } emitter.foot_comment = emitter.foot_comment[:0] + emitter.foot_indent = emitter.indent + if emitter.foot_indent < 0 { + emitter.foot_indent = 0 + } return true } @@ -1478,6 +1469,11 @@ func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool { return false } } + if emitter.foot_indent == indent { + if !put_break(emitter) { + return false + } + } for emitter.column < indent { if !put(emitter, ' ') { return false @@ -1486,6 +1482,7 @@ func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool { emitter.whitespace = true //emitter.indention = true emitter.space_above = false + emitter.foot_indent = -1 return true } @@ -1582,7 +1579,7 @@ func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_ } func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { - if !emitter.whitespace { + if len(value) > 0 && !emitter.whitespace { if !put(emitter, ' ') { return false } @@ -1629,7 +1626,9 @@ func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allo } } - emitter.whitespace = false + if len(value) > 0 { + emitter.whitespace = false + } emitter.indention = false if emitter.root_context { emitter.open_ended = true diff --git a/vendor/gopkg.in/yaml.v3/encode.go b/vendor/gopkg.in/yaml.v3/encode.go index 38882b50e1..eee3667eab 100644 --- a/vendor/gopkg.in/yaml.v3/encode.go +++ b/vendor/gopkg.in/yaml.v3/encode.go @@ -485,7 +485,11 @@ func (e *encoder) node(node *Node, tail string) { for i := 0; i+1 < len(node.Content); i += 2 { k := node.Content[i] foot := k.FootComment - k.FootComment = "" + if foot != "" { + kopy := *k + kopy.FootComment = "" + k = &kopy + } e.node(k, tail) tail = foot diff --git a/vendor/gopkg.in/yaml.v3/scannerc.go b/vendor/gopkg.in/yaml.v3/scannerc.go index ded66e80df..e33f495906 100644 --- a/vendor/gopkg.in/yaml.v3/scannerc.go +++ b/vendor/gopkg.in/yaml.v3/scannerc.go @@ -758,7 +758,7 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) { } comment_mark := parser.mark - if parser.flow_level > 0 && buf[pos] == ',' && len(parser.tokens) > 0 { + if len(parser.tokens) > 0 && (parser.flow_level == 0 && buf[pos] == ':' || parser.flow_level > 0 && buf[pos] == ',') { // Associate any following comments with the prior token. comment_mark = parser.tokens[len(parser.tokens)-1].start_mark } @@ -961,6 +961,9 @@ func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { return true } +// max_flow_level limits the flow_level +const max_flow_level = 10000 + // Increase the flow level and resize the simple key list if needed. func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { // Reset the simple key on the next level. @@ -968,6 +971,11 @@ func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { // Increase the flow level. parser.flow_level++ + if parser.flow_level > max_flow_level { + return yaml_parser_set_scanner_error(parser, + "while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark, + fmt.Sprintf("exceeded max depth of %d", max_flow_level)) + } return true } @@ -980,6 +988,9 @@ func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { return true } +// max_indents limits the indents stack size +const max_indents = 10000 + // Push the current indentation level to the stack and set the new level // the current column is greater than the indentation level. In this case, // append or insert the specified token into the token queue. @@ -994,6 +1005,11 @@ func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml // indentation level. parser.indents = append(parser.indents, parser.indent) parser.indent = column + if len(parser.indents) > max_indents { + return yaml_parser_set_scanner_error(parser, + "while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark, + fmt.Sprintf("exceeded max depth of %d", max_indents)) + } // Create a token and insert it into the queue. token := yaml_token_t{ @@ -2839,7 +2855,7 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo var start_mark yaml_mark_t var recent_empty = false - var first_empty = true + var first_empty = parser.newlines <= 1 var line = parser.mark.line var column = parser.mark.column @@ -2848,11 +2864,14 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo // The foot line is the place where a comment must start to // still be considered as a foot of the prior content. - // If there's some content in the currently parsed line, then the foot - // is the line below it. - var foot_line = parser.mark.line-parser.newlines+1 - if parser.newlines == 0 && parser.mark.column > 1 { - foot_line++ + // If there's some content in the currently parsed line, then + // the foot is the line below it. + var foot_line = -1 + if scan_mark.line > 0 { + foot_line = parser.mark.line-parser.newlines+1 + if parser.newlines == 0 && parser.mark.column > 1 { + foot_line++ + } } var peek = 0 @@ -2868,11 +2887,15 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo if is_breakz(parser.buffer, parser.buffer_pos+peek) || parser.flow_level > 0 && (c == ']' || c == '}') { // Got line break or terminator. if !recent_empty { - if first_empty && (start_mark.line > 0 && start_mark.line == foot_line || start_mark.column-1 < parser.indent) { + if first_empty && (start_mark.line == foot_line || start_mark.column-1 < parser.indent) { // This is the first empty line and there were no empty lines before, // so this initial part of the comment is a foot of the prior token // instead of being a head for the following one. Split it up. if len(text) > 0 { + if start_mark.column-1 < parser.indent { + // If dedented it's unrelated to the prior token. + token_mark = start_mark + } parser.comments = append(parser.comments, yaml_comment_t{ scan_mark: scan_mark, token_mark: token_mark, diff --git a/vendor/gopkg.in/yaml.v3/yamlh.go b/vendor/gopkg.in/yaml.v3/yamlh.go index acdc0f6faf..65fb0df3b1 100644 --- a/vendor/gopkg.in/yaml.v3/yamlh.go +++ b/vendor/gopkg.in/yaml.v3/yamlh.go @@ -753,7 +753,8 @@ type yaml_emitter_t struct { indention bool // If the last character was an indentation character (' ', '-', '?', ':')? open_ended bool // If an explicit document end is required? - space_above bool // If there's an empty line right above? + space_above bool // Is there's an empty line above? + foot_indent int // The indent used to write the foot comment above, or -1 if none. // Anchor analysis. anchor_data struct { diff --git a/vendor/knative.dev/eventing/pkg/apis/duck/v1/channelable_types.go b/vendor/knative.dev/eventing/pkg/apis/duck/v1/channelable_types.go new file mode 100644 index 0000000000..2e177fe9ac --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/duck/v1/channelable_types.go @@ -0,0 +1,152 @@ +/* +Copyright 2020 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 v1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "knative.dev/pkg/apis" + "knative.dev/pkg/apis/duck" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +// +genduck +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Channelable is a skeleton type wrapping Subscribable and Addressable in the manner we expect resource writers +// defining compatible resources to embed it. We will typically use this type to deserialize +// Channelable ObjectReferences and access their subscription and address data. This is not a real resource. +type Channelable struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec is the part where the Channelable fulfills the Subscribable contract. + Spec ChannelableSpec `json:"spec,omitempty"` + + Status ChannelableStatus `json:"status,omitempty"` +} + +// ChannelableSpec contains Spec of the Channelable object +type ChannelableSpec struct { + SubscribableSpec `json:",inline"` + + // DeliverySpec contains options controlling the event delivery + // +optional + Delivery *DeliverySpec `json:"delivery,omitempty"` +} + +// ChannelableStatus contains the Status of a Channelable object. +type ChannelableStatus struct { + // inherits duck/v1 Status, which currently provides: + // * ObservedGeneration - the 'Generation' of the Service that was last processed by the controller. + // * Conditions - the latest available observations of a resource's current state. + duckv1.Status `json:",inline"` + // AddressStatus is the part where the Channelable fulfills the Addressable contract. + duckv1.AddressStatus `json:",inline"` + // Subscribers is populated with the statuses of each of the Channelable's subscribers. + SubscribableStatus `json:",inline"` + // DeadLetterChannel is a KReference and is set by the channel when it supports native error handling via a channel + // Failed messages are delivered here. + // +optional + DeadLetterChannel *duckv1.KReference `json:"deadLetterChannel,omitempty"` +} + +var ( + // Verify Channelable resources meet duck contracts. + _ duck.Populatable = (*Channelable)(nil) + _ duck.Implementable = (*Channelable)(nil) + _ apis.Listable = (*Channelable)(nil) +) + +// Populate implements duck.Populatable +func (c *Channelable) Populate() { + c.Spec.SubscribableSpec = SubscribableSpec{ + // Populate ALL fields + Subscribers: []SubscriberSpec{{ + UID: "2f9b5e8e-deb6-11e8-9f32-f2801f1b9fd1", + Generation: 1, + SubscriberURI: apis.HTTP("call1"), + ReplyURI: apis.HTTP("sink2"), + }, { + UID: "34c5aec8-deb6-11e8-9f32-f2801f1b9fd1", + Generation: 2, + SubscriberURI: apis.HTTP("call2"), + ReplyURI: apis.HTTP("sink2"), + }}, + } + retry := int32(5) + linear := BackoffPolicyLinear + delay := "5s" + c.Spec.Delivery = &DeliverySpec{ + DeadLetterSink: &duckv1.Destination{ + Ref: &duckv1.KReference{ + Name: "aname", + }, + URI: &apis.URL{ + Scheme: "http", + Host: "test-error-domain", + }, + }, + Retry: &retry, + BackoffPolicy: &linear, + BackoffDelay: &delay, + } + c.Status = ChannelableStatus{ + AddressStatus: duckv1.AddressStatus{ + Address: &duckv1.Addressable{ + URL: &apis.URL{ + Scheme: "http", + Host: "test-domain", + }, + }, + }, + SubscribableStatus: SubscribableStatus{ + Subscribers: []SubscriberStatus{{ + UID: "2f9b5e8e-deb6-11e8-9f32-f2801f1b9fd1", + ObservedGeneration: 1, + Ready: corev1.ConditionTrue, + Message: "Some message", + }, { + UID: "34c5aec8-deb6-11e8-9f32-f2801f1b9fd1", + ObservedGeneration: 2, + Ready: corev1.ConditionFalse, + Message: "Some message", + }}, + }, + } +} + +// GetFullType implements duck.Implementable +func (s *Channelable) GetFullType() duck.Populatable { + return &Channelable{} +} + +// GetListType implements apis.Listable +func (c *Channelable) GetListType() runtime.Object { + return &ChannelableList{} +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ChannelableList is a list of Channelable resources. +type ChannelableList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []Channelable `json:"items"` +} diff --git a/vendor/knative.dev/eventing/pkg/apis/duck/v1/delivery_conversion.go b/vendor/knative.dev/eventing/pkg/apis/duck/v1/delivery_conversion.go new file mode 100644 index 0000000000..bae7a804ec --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/duck/v1/delivery_conversion.go @@ -0,0 +1,44 @@ +/* +Copyright 2020 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 v1 + +import ( + "context" + "fmt" + + "knative.dev/pkg/apis" +) + +// ConvertTo implements apis.Convertible +func (source *DeliverySpec) ConvertTo(ctx context.Context, sink apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", sink) +} + +// ConvertFrom implements apis.Convertible +func (sink *DeliverySpec) ConvertFrom(ctx context.Context, source apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", source) +} + +// ConvertTo implements apis.Convertible +func (source *DeliveryStatus) ConvertTo(ctx context.Context, sink apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", sink) +} + +// ConvertFrom implements apis.Convertible +func (sink *DeliveryStatus) ConvertFrom(ctx context.Context, source apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", source) +} diff --git a/vendor/knative.dev/eventing/pkg/apis/duck/v1/delivery_types.go b/vendor/knative.dev/eventing/pkg/apis/duck/v1/delivery_types.go new file mode 100644 index 0000000000..70c2b280b4 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/duck/v1/delivery_types.go @@ -0,0 +1,95 @@ +/* +Copyright 2020 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 v1 + +import ( + "context" + "time" + + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +// DeliverySpec contains the delivery options for event senders, +// such as channelable and source. +type DeliverySpec struct { + // DeadLetterSink is the sink receiving event that could not be sent to + // a destination. + // +optional + DeadLetterSink *duckv1.Destination `json:"deadLetterSink,omitempty"` + + // Retry is the minimum number of retries the sender should attempt when + // sending an event before moving it to the dead letter sink. + // +optional + Retry *int32 `json:"retry,omitempty"` + + // BackoffPolicy is the retry backoff policy (linear, exponential). + // +optional + BackoffPolicy *BackoffPolicyType `json:"backoffPolicy,omitempty"` + + // BackoffDelay is the delay before retrying. + // More information on Duration format: https://www.ietf.org/rfc/rfc3339.txt + // + // For linear policy, backoff delay is the time interval between retries. + // For exponential policy , backoff delay is backoffDelay*2^. + // +optional + BackoffDelay *string `json:"backoffDelay,omitempty"` +} + +func (ds *DeliverySpec) Validate(ctx context.Context) *apis.FieldError { + if ds == nil { + return nil + } + var errs *apis.FieldError + if dlse := ds.DeadLetterSink.Validate(ctx); dlse != nil { + errs = errs.Also(dlse).ViaField("deadLetterSink") + } + if ds.BackoffPolicy != nil { + switch *ds.BackoffPolicy { + case BackoffPolicyExponential, BackoffPolicyLinear: + // nothing + default: + errs = errs.Also(apis.ErrInvalidValue(*ds.BackoffPolicy, "backoffPolicy")) + } + } + if ds.BackoffDelay != nil { + _, te := time.Parse(time.RFC3339, *ds.BackoffDelay) + if te != nil { + errs = errs.Also(apis.ErrInvalidValue(*ds.BackoffDelay, "backoffDelay")) + } + } + return errs +} + +// BackoffPolicyType is the type for backoff policies +type BackoffPolicyType string + +const ( + // Linear backoff policy + BackoffPolicyLinear BackoffPolicyType = "linear" + + // Exponential backoff policy + BackoffPolicyExponential BackoffPolicyType = "exponential" +) + +// DeliveryStatus contains the Status of an object supporting delivery options. +type DeliveryStatus struct { + // DeadLetterChannel is a KReference that is the reference to the native, platform specific channel + // where failed events are sent to. + // +optional + DeadLetterChannel *duckv1.KReference `json:"deadLetterChannel,omitempty"` +} diff --git a/vendor/knative.dev/eventing/pkg/apis/duck/v1/doc.go b/vendor/knative.dev/eventing/pkg/apis/duck/v1/doc.go new file mode 100644 index 0000000000..ff5ac0c20b --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/duck/v1/doc.go @@ -0,0 +1,24 @@ +/* +Copyright 2020 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. +*/ + +// Api versions allow the api contract for a resource to be changed while keeping +// backward compatibility by support multiple concurrent versions +// of the same resource + +// Package v1 is the v1 version of the API. +// +k8s:deepcopy-gen=package +// +groupName=duck.knative.dev +package v1 diff --git a/vendor/knative.dev/eventing/pkg/apis/duck/v1/subscribable_types.go b/vendor/knative.dev/eventing/pkg/apis/duck/v1/subscribable_types.go new file mode 100644 index 0000000000..b744334e19 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/duck/v1/subscribable_types.go @@ -0,0 +1,157 @@ +/* +Copyright 2020 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 v1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "knative.dev/pkg/apis" + "knative.dev/pkg/apis/duck" +) + +// +genduck + +var _ duck.Implementable = (*Subscribable)(nil) + +// SubscriberSpec defines a single subscriber to a Subscribable. +// +// At least one of SubscriberURI and ReplyURI must be present +type SubscriberSpec struct { + // UID is used to understand the origin of the subscriber. + // +optional + UID types.UID `json:"uid,omitempty"` + // Generation of the origin of the subscriber with uid:UID. + // +optional + Generation int64 `json:"generation,omitempty"` + // SubscriberURI is the endpoint for the subscriber + // +optional + SubscriberURI *apis.URL `json:"subscriberUri,omitempty"` + // ReplyURI is the endpoint for the reply + // +optional + ReplyURI *apis.URL `json:"replyUri,omitempty"` + // +optional + // DeliverySpec contains options controlling the event delivery + // +optional + Delivery *DeliverySpec `json:"delivery,omitempty"` +} + +// SubscriberStatus defines the status of a single subscriber to a Channel. +type SubscriberStatus struct { + // UID is used to understand the origin of the subscriber. + // +optional + UID types.UID `json:"uid,omitempty"` + // Generation of the origin of the subscriber with uid:UID. + // +optional + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + // Status of the subscriber. + Ready corev1.ConditionStatus `json:"ready,omitempty"` + // A human readable message indicating details of Ready status. + // +optional + Message string `json:"message,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Subscribable is a skeleton type wrapping Subscribable in the manner we expect resource writers +// defining compatible resources to embed it. We will typically use this type to deserialize +// SubscribableType ObjectReferences and access the Subscription data. This is not a real resource. +type Subscribable struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // SubscribableSpec is the part where Subscribable object is + // configured as to be compatible with Subscribable contract. + Spec SubscribableSpec `json:"spec"` + + // SubscribableStatus is the part where SubscribableStatus object is + // configured as to be compatible with Subscribable contract. + Status SubscribableStatus `json:"status"` +} + +// SubscribableSpec shows how we expect folks to embed Subscribable in their Spec field. +type SubscribableSpec struct { + // This is the list of subscriptions for this subscribable. + // +patchMergeKey=uid + // +patchStrategy=merge + Subscribers []SubscriberSpec `json:"subscribers,omitempty" patchStrategy:"merge" patchMergeKey:"uid"` +} + +// SubscribableStatus is the schema for the subscribable's status portion of the status +// section of the resource. +type SubscribableStatus struct { + // This is the list of subscription's statuses for this channel. + // +patchMergeKey=uid + // +patchStrategy=merge + Subscribers []SubscriberStatus `json:"subscribers,omitempty" patchStrategy:"merge" patchMergeKey:"uid"` +} + +var ( + // Verify SubscribableType resources meet duck contracts. + _ duck.Populatable = (*Subscribable)(nil) + _ apis.Listable = (*Subscribable)(nil) + + _ apis.Convertible = (*Subscribable)(nil) +) + +// GetFullType implements duck.Implementable +func (s *Subscribable) GetFullType() duck.Populatable { + return &Subscribable{} +} + +// Populate implements duck.Populatable +func (c *Subscribable) Populate() { + c.Spec.Subscribers = []SubscriberSpec{{ + UID: "2f9b5e8e-deb6-11e8-9f32-f2801f1b9fd1", + Generation: 1, + SubscriberURI: apis.HTTP("call1"), + ReplyURI: apis.HTTP("sink2"), + }, { + UID: "34c5aec8-deb6-11e8-9f32-f2801f1b9fd1", + Generation: 2, + SubscriberURI: apis.HTTP("call2"), + ReplyURI: apis.HTTP("sink2"), + }} + c.Status.Subscribers = // Populate ALL fields + []SubscriberStatus{{ + UID: "2f9b5e8e-deb6-11e8-9f32-f2801f1b9fd1", + ObservedGeneration: 1, + Ready: corev1.ConditionTrue, + Message: "Some message", + }, { + UID: "34c5aec8-deb6-11e8-9f32-f2801f1b9fd1", + ObservedGeneration: 2, + Ready: corev1.ConditionFalse, + Message: "Some message", + }} +} + +// GetListType implements apis.Listable +func (c *Subscribable) GetListType() runtime.Object { + return &SubscribableList{} +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// SubscribableTypeList is a list of SubscribableType resources +type SubscribableList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []Subscribable `json:"items"` +} diff --git a/vendor/knative.dev/eventing/pkg/apis/duck/v1/subscribable_types_conversion.go b/vendor/knative.dev/eventing/pkg/apis/duck/v1/subscribable_types_conversion.go new file mode 100644 index 0000000000..b61470ddac --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/duck/v1/subscribable_types_conversion.go @@ -0,0 +1,34 @@ +/* +Copyright 2020 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 v1 + +import ( + "context" + "fmt" + + "knative.dev/pkg/apis" +) + +// ConvertTo implements apis.Convertible +func (source *Subscribable) ConvertTo(ctx context.Context, sink apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", sink) +} + +// ConvertFrom implements apis.Convertible +func (sink *Subscribable) ConvertFrom(ctx context.Context, source apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", source) +} diff --git a/vendor/knative.dev/eventing/pkg/apis/duck/v1/zz_generated.deepcopy.go b/vendor/knative.dev/eventing/pkg/apis/duck/v1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..253cf94fc7 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/duck/v1/zz_generated.deepcopy.go @@ -0,0 +1,343 @@ +// +build !ignore_autogenerated + +/* +Copyright 2020 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. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" + apis "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Channelable) DeepCopyInto(out *Channelable) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Channelable. +func (in *Channelable) DeepCopy() *Channelable { + if in == nil { + return nil + } + out := new(Channelable) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Channelable) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ChannelableList) DeepCopyInto(out *ChannelableList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Channelable, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ChannelableList. +func (in *ChannelableList) DeepCopy() *ChannelableList { + if in == nil { + return nil + } + out := new(ChannelableList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ChannelableList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ChannelableSpec) DeepCopyInto(out *ChannelableSpec) { + *out = *in + in.SubscribableSpec.DeepCopyInto(&out.SubscribableSpec) + if in.Delivery != nil { + in, out := &in.Delivery, &out.Delivery + *out = new(DeliverySpec) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ChannelableSpec. +func (in *ChannelableSpec) DeepCopy() *ChannelableSpec { + if in == nil { + return nil + } + out := new(ChannelableSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ChannelableStatus) DeepCopyInto(out *ChannelableStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + in.AddressStatus.DeepCopyInto(&out.AddressStatus) + in.SubscribableStatus.DeepCopyInto(&out.SubscribableStatus) + if in.DeadLetterChannel != nil { + in, out := &in.DeadLetterChannel, &out.DeadLetterChannel + *out = new(duckv1.KReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ChannelableStatus. +func (in *ChannelableStatus) DeepCopy() *ChannelableStatus { + if in == nil { + return nil + } + out := new(ChannelableStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeliverySpec) DeepCopyInto(out *DeliverySpec) { + *out = *in + if in.DeadLetterSink != nil { + in, out := &in.DeadLetterSink, &out.DeadLetterSink + *out = new(duckv1.Destination) + (*in).DeepCopyInto(*out) + } + if in.Retry != nil { + in, out := &in.Retry, &out.Retry + *out = new(int32) + **out = **in + } + if in.BackoffPolicy != nil { + in, out := &in.BackoffPolicy, &out.BackoffPolicy + *out = new(BackoffPolicyType) + **out = **in + } + if in.BackoffDelay != nil { + in, out := &in.BackoffDelay, &out.BackoffDelay + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeliverySpec. +func (in *DeliverySpec) DeepCopy() *DeliverySpec { + if in == nil { + return nil + } + out := new(DeliverySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeliveryStatus) DeepCopyInto(out *DeliveryStatus) { + *out = *in + if in.DeadLetterChannel != nil { + in, out := &in.DeadLetterChannel, &out.DeadLetterChannel + *out = new(duckv1.KReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeliveryStatus. +func (in *DeliveryStatus) DeepCopy() *DeliveryStatus { + if in == nil { + return nil + } + out := new(DeliveryStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Subscribable) DeepCopyInto(out *Subscribable) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Subscribable. +func (in *Subscribable) DeepCopy() *Subscribable { + if in == nil { + return nil + } + out := new(Subscribable) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Subscribable) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscribableList) DeepCopyInto(out *SubscribableList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Subscribable, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscribableList. +func (in *SubscribableList) DeepCopy() *SubscribableList { + if in == nil { + return nil + } + out := new(SubscribableList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *SubscribableList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscribableSpec) DeepCopyInto(out *SubscribableSpec) { + *out = *in + if in.Subscribers != nil { + in, out := &in.Subscribers, &out.Subscribers + *out = make([]SubscriberSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscribableSpec. +func (in *SubscribableSpec) DeepCopy() *SubscribableSpec { + if in == nil { + return nil + } + out := new(SubscribableSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscribableStatus) DeepCopyInto(out *SubscribableStatus) { + *out = *in + if in.Subscribers != nil { + in, out := &in.Subscribers, &out.Subscribers + *out = make([]SubscriberStatus, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscribableStatus. +func (in *SubscribableStatus) DeepCopy() *SubscribableStatus { + if in == nil { + return nil + } + out := new(SubscribableStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriberSpec) DeepCopyInto(out *SubscriberSpec) { + *out = *in + if in.SubscriberURI != nil { + in, out := &in.SubscriberURI, &out.SubscriberURI + *out = new(apis.URL) + (*in).DeepCopyInto(*out) + } + if in.ReplyURI != nil { + in, out := &in.ReplyURI, &out.ReplyURI + *out = new(apis.URL) + (*in).DeepCopyInto(*out) + } + if in.Delivery != nil { + in, out := &in.Delivery, &out.Delivery + *out = new(DeliverySpec) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriberSpec. +func (in *SubscriberSpec) DeepCopy() *SubscriberSpec { + if in == nil { + return nil + } + out := new(SubscriberSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriberStatus) DeepCopyInto(out *SubscriberStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriberStatus. +func (in *SubscriberStatus) DeepCopy() *SubscriberStatus { + if in == nil { + return nil + } + out := new(SubscriberStatus) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/subscribable_types_conversion.go b/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/subscribable_types_conversion.go index cfaf63cb47..9d5f6ace04 100644 --- a/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/subscribable_types_conversion.go +++ b/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/subscribable_types_conversion.go @@ -24,7 +24,6 @@ import ( duckv1 "knative.dev/pkg/apis/duck/v1" duckv1beta1 "knative.dev/eventing/pkg/apis/duck/v1beta1" - eventingduckv1beta1 "knative.dev/eventing/pkg/apis/duck/v1beta1" ) // ConvertTo implements apis.Convertible @@ -87,7 +86,7 @@ func (source *SubscribableTypeStatus) ConvertTo(ctx context.Context, sink *duckv } // ConvertFrom implements apis.Convertible. -// Converts obj v1beta1.Subscribable into v1alpha1.Subscribable +// Converts obj v1beta1.Subscribable into v1alpha1.SubscribableType func (sink *SubscribableType) ConvertFrom(ctx context.Context, obj apis.Convertible) error { switch source := obj.(type) { case *duckv1beta1.Subscribable: @@ -112,6 +111,7 @@ func (sink *SubscribableTypeSpec) ConvertFrom(ctx context.Context, source duckv1 } } +// ConvertFrom helps implement apis.Convertible func (sink *SubscriberSpec) ConvertFrom(ctx context.Context, source duckv1beta1.SubscriberSpec) { var deadLetterSinkURI *apis.URL if source.Delivery != nil && source.Delivery.DeadLetterSink != nil { @@ -130,10 +130,10 @@ func (sink *SubscriberSpec) ConvertFrom(ctx context.Context, source duckv1beta1. func (sink *SubscribableTypeStatus) ConvertFrom(ctx context.Context, source duckv1beta1.SubscribableStatus) error { if len(source.Subscribers) > 0 { sink.SubscribableStatus = &SubscribableStatus{ - Subscribers: make([]eventingduckv1beta1.SubscriberStatus, len(source.Subscribers)), + Subscribers: make([]duckv1beta1.SubscriberStatus, len(source.Subscribers)), } for i, ss := range source.Subscribers { - sink.SubscribableStatus.Subscribers[i] = eventingduckv1beta1.SubscriberStatus{ + sink.SubscribableStatus.Subscribers[i] = duckv1beta1.SubscriberStatus{ UID: ss.UID, ObservedGeneration: ss.ObservedGeneration, Ready: ss.Ready, diff --git a/vendor/knative.dev/eventing/pkg/apis/duck/v1beta1/delivery_conversion.go b/vendor/knative.dev/eventing/pkg/apis/duck/v1beta1/delivery_conversion.go index 07a729884c..8601032c94 100644 --- a/vendor/knative.dev/eventing/pkg/apis/duck/v1beta1/delivery_conversion.go +++ b/vendor/knative.dev/eventing/pkg/apis/duck/v1beta1/delivery_conversion.go @@ -21,24 +21,68 @@ import ( "fmt" "knative.dev/pkg/apis" + + eventingduckv1 "knative.dev/eventing/pkg/apis/duck/v1" ) // ConvertTo implements apis.Convertible -func (source *DeliverySpec) ConvertTo(ctx context.Context, sink apis.Convertible) error { - return fmt.Errorf("v1beta1 is the highest known version, got: %T", sink) +func (source *DeliverySpec) ConvertTo(ctx context.Context, to apis.Convertible) error { + switch sink := to.(type) { + case *eventingduckv1.DeliverySpec: + sink.Retry = source.Retry + sink.BackoffDelay = source.BackoffDelay + if *source.BackoffPolicy == BackoffPolicyLinear { + linear := eventingduckv1.BackoffPolicyLinear + sink.BackoffPolicy = &linear + } else if *source.BackoffPolicy == BackoffPolicyExponential { + exponential := eventingduckv1.BackoffPolicyExponential + sink.BackoffPolicy = &exponential + } + sink.DeadLetterSink = source.DeadLetterSink + return nil + default: + return fmt.Errorf("unknown version, got: %T", sink) + } } // ConvertFrom implements apis.Convertible -func (sink *DeliverySpec) ConvertFrom(ctx context.Context, source apis.Convertible) error { - return fmt.Errorf("v1beta1 is the highest known version, got: %T", source) +func (sink *DeliverySpec) ConvertFrom(ctx context.Context, from apis.Convertible) error { + switch source := from.(type) { + case *eventingduckv1.DeliverySpec: + sink.Retry = source.Retry + sink.BackoffDelay = source.BackoffDelay + if *source.BackoffPolicy == eventingduckv1.BackoffPolicyLinear { + linear := BackoffPolicyLinear + sink.BackoffPolicy = &linear + } else if *source.BackoffPolicy == eventingduckv1.BackoffPolicyExponential { + exponential := BackoffPolicyExponential + sink.BackoffPolicy = &exponential + } + sink.DeadLetterSink = source.DeadLetterSink + return nil + default: + return fmt.Errorf("unknown version, got: %T", source) + } } // ConvertTo implements apis.Convertible -func (source *DeliveryStatus) ConvertTo(ctx context.Context, sink apis.Convertible) error { - return fmt.Errorf("v1beta1 is the highest known version, got: %T", sink) +func (source *DeliveryStatus) ConvertTo(ctx context.Context, to apis.Convertible) error { + switch sink := to.(type) { + case *eventingduckv1.DeliveryStatus: + sink.DeadLetterChannel = source.DeadLetterChannel + return nil + default: + return fmt.Errorf("unknown version, got: %T", sink) + } } // ConvertFrom implements apis.Convertible -func (sink *DeliveryStatus) ConvertFrom(ctx context.Context, source apis.Convertible) error { - return fmt.Errorf("v1beta1 is the highest known version, got: %T", source) +func (sink *DeliveryStatus) ConvertFrom(ctx context.Context, from apis.Convertible) error { + switch source := from.(type) { + case *eventingduckv1.DeliveryStatus: + sink.DeadLetterChannel = source.DeadLetterChannel + return nil + default: + return fmt.Errorf("unknown version, got: %T", source) + } } diff --git a/vendor/knative.dev/eventing/pkg/apis/duck/v1beta1/subscribable_types_conversion.go b/vendor/knative.dev/eventing/pkg/apis/duck/v1beta1/subscribable_types_conversion.go index f25a6755ce..e6f4c4a98a 100644 --- a/vendor/knative.dev/eventing/pkg/apis/duck/v1beta1/subscribable_types_conversion.go +++ b/vendor/knative.dev/eventing/pkg/apis/duck/v1beta1/subscribable_types_conversion.go @@ -21,14 +21,109 @@ import ( "fmt" "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" + + eventingduckv1 "knative.dev/eventing/pkg/apis/duck/v1" ) // ConvertTo implements apis.Convertible -func (source *Subscribable) ConvertTo(ctx context.Context, sink apis.Convertible) error { - return fmt.Errorf("v1beta1 is the highest known version, got: %T", sink) +func (source *Subscribable) ConvertTo(ctx context.Context, to apis.Convertible) error { + switch sink := to.(type) { + case *eventingduckv1.Subscribable: + sink.ObjectMeta = source.ObjectMeta + source.Status.ConvertTo(ctx, &sink.Status) + source.Spec.ConvertTo(ctx, &sink.Spec) + return nil + default: + return fmt.Errorf("unknown version, got: %T", sink) + } +} + +// ConvertTo helps implement apis.Convertible +func (source *SubscribableSpec) ConvertTo(ctx context.Context, sink *eventingduckv1.SubscribableSpec) { + if len(source.Subscribers) > 0 { + sink.Subscribers = make([]eventingduckv1.SubscriberSpec, len(source.Subscribers)) + for i, s := range source.Subscribers { + s.ConvertTo(ctx, &sink.Subscribers[i]) + } + } + +} + +// ConvertTo helps implement apis.Convertible +func (source *SubscriberSpec) ConvertTo(ctx context.Context, sink *eventingduckv1.SubscriberSpec) { + sink.UID = source.UID + sink.Generation = source.Generation + sink.SubscriberURI = source.SubscriberURI + sink.Delivery = &eventingduckv1.DeliverySpec{ + DeadLetterSink: &duckv1.Destination{}, + } + source.Delivery.ConvertTo(ctx, sink.Delivery) + sink.ReplyURI = source.ReplyURI +} + +// ConvertTo helps implement apis.Convertible +func (source *SubscribableStatus) ConvertTo(ctx context.Context, sink *eventingduckv1.SubscribableStatus) { + if len(source.Subscribers) > 0 { + sink.Subscribers = make([]eventingduckv1.SubscriberStatus, len(source.Subscribers)) + for i, ss := range source.Subscribers { + sink.Subscribers[i] = eventingduckv1.SubscriberStatus{ + UID: ss.UID, + ObservedGeneration: ss.ObservedGeneration, + Ready: ss.Ready, + Message: ss.Message, + } + } + } +} + +// ConvertFrom implements apis.Convertible. +func (sink *Subscribable) ConvertFrom(ctx context.Context, from apis.Convertible) error { + switch source := from.(type) { + case *eventingduckv1.Subscribable: + sink.ObjectMeta = source.ObjectMeta + sink.Status.ConvertFrom(ctx, source.Status) + sink.Spec.ConvertFrom(ctx, source.Spec) + return nil + default: + return fmt.Errorf("unknown version, got: %T", source) + } +} + +// ConvertFrom helps implement apis.Convertible +func (sink *SubscribableSpec) ConvertFrom(ctx context.Context, source eventingduckv1.SubscribableSpec) { + if len(source.Subscribers) > 0 { + sink.Subscribers = make([]SubscriberSpec, len(source.Subscribers)) + for i, s := range source.Subscribers { + sink.Subscribers[i].ConvertFrom(ctx, s) + } + } +} + +// ConvertFrom helps implement apis.Convertible +func (sink *SubscriberSpec) ConvertFrom(ctx context.Context, source eventingduckv1.SubscriberSpec) { + sink.UID = source.UID + sink.Generation = source.Generation + sink.SubscriberURI = source.SubscriberURI + sink.ReplyURI = source.ReplyURI + sink.Delivery = &DeliverySpec{ + DeadLetterSink: &duckv1.Destination{}, + } + sink.Delivery.ConvertFrom(ctx, source.Delivery) } -// ConvertFrom implements apis.Convertible -func (sink *Subscribable) ConvertFrom(ctx context.Context, source apis.Convertible) error { - return fmt.Errorf("v1beta1 is the highest known version, got: %T", source) +// ConvertFrom helps implement apis.Convertible +func (sink *SubscribableStatus) ConvertFrom(ctx context.Context, source eventingduckv1.SubscribableStatus) error { + if len(source.Subscribers) > 0 { + sink.Subscribers = make([]SubscriberStatus, len(source.Subscribers)) + for i, ss := range source.Subscribers { + sink.Subscribers[i] = SubscriberStatus{ + UID: ss.UID, + ObservedGeneration: ss.ObservedGeneration, + Ready: ss.Ready, + Message: ss.Message, + } + } + } + return nil } diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_conversion.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_conversion.go new file mode 100644 index 0000000000..30f555c43b --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_conversion.go @@ -0,0 +1,34 @@ +/* +Copyright 2020 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 v1 + +import ( + "context" + "fmt" + + "knative.dev/pkg/apis" +) + +// ConvertTo implements apis.Convertible +func (source *Broker) ConvertTo(ctx context.Context, sink apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", sink) +} + +// ConvertFrom implements apis.Convertible +func (sink *Broker) ConvertFrom(ctx context.Context, source apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", source) +} diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_defaults.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_defaults.go new file mode 100644 index 0000000000..2ae42be8e7 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_defaults.go @@ -0,0 +1,47 @@ +/* +Copyright 2020 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 v1 + +import ( + "context" + + "knative.dev/eventing/pkg/apis/config" + "knative.dev/eventing/pkg/apis/eventing" + "knative.dev/pkg/apis" +) + +func (b *Broker) SetDefaults(ctx context.Context) { + // Default Spec fields. + withNS := apis.WithinParent(ctx, b.ObjectMeta) + b.Spec.SetDefaults(withNS) + eventing.DefaultBrokerClassIfUnset(withNS, &b.ObjectMeta) +} + +func (bs *BrokerSpec) SetDefaults(ctx context.Context) { + if bs.Config != nil { + // Default the namespace if not given + bs.Config.SetDefaults(ctx) + return + } + + cfg := config.FromContextOrDefaults(ctx) + c, err := cfg.Defaults.GetBrokerConfig(apis.ParentMeta(ctx).Namespace) + if err == nil { + c.SetDefaults(ctx) + bs.Config = c + } +} diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_lifecycle.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_lifecycle.go new file mode 100644 index 0000000000..ebd71cde53 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_lifecycle.go @@ -0,0 +1,114 @@ +/* +Copyright 2020 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 v1 + +import ( + corev1 "k8s.io/api/core/v1" + + "knative.dev/eventing/pkg/apis/duck" + duckv1 "knative.dev/eventing/pkg/apis/duck/v1" + "knative.dev/pkg/apis" +) + +var brokerCondSet = apis.NewLivingConditionSet( + BrokerConditionIngress, + BrokerConditionTriggerChannel, + BrokerConditionFilter, + BrokerConditionAddressable, +) + +const ( + BrokerConditionReady = apis.ConditionReady + BrokerConditionIngress apis.ConditionType = "IngressReady" + BrokerConditionTriggerChannel apis.ConditionType = "TriggerChannelReady" + BrokerConditionFilter apis.ConditionType = "FilterReady" + BrokerConditionAddressable apis.ConditionType = "Addressable" +) + +// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface. +func (*Broker) GetConditionSet() apis.ConditionSet { + return brokerCondSet +} + +// GetTopLevelCondition returns the top level Condition. +func (bs *BrokerStatus) GetTopLevelCondition() *apis.Condition { + return brokerCondSet.Manage(bs).GetTopLevelCondition() +} + +// SetAddress makes this Broker addressable by setting the URI. It also +// sets the BrokerConditionAddressable to true. +func (bs *BrokerStatus) SetAddress(url *apis.URL) { + bs.Address.URL = url + if url != nil { + brokerCondSet.Manage(bs).MarkTrue(BrokerConditionAddressable) + } else { + brokerCondSet.Manage(bs).MarkFalse(BrokerConditionAddressable, "nil URL", "URL is nil") + } +} + +// GetCondition returns the condition currently associated with the given type, or nil. +func (bs *BrokerStatus) GetCondition(t apis.ConditionType) *apis.Condition { + return brokerCondSet.Manage(bs).GetCondition(t) +} + +// IsReady returns true if the resource is ready overall. +func (bs *BrokerStatus) IsReady() bool { + return brokerCondSet.Manage(bs).IsHappy() +} + +// InitializeConditions sets relevant unset conditions to Unknown state. +func (bs *BrokerStatus) InitializeConditions() { + brokerCondSet.Manage(bs).InitializeConditions() +} + +func (bs *BrokerStatus) MarkIngressFailed(reason, format string, args ...interface{}) { + brokerCondSet.Manage(bs).MarkFalse(BrokerConditionIngress, reason, format, args...) +} + +func (bs *BrokerStatus) PropagateIngressAvailability(ep *corev1.Endpoints) { + if duck.EndpointsAreAvailable(ep) { + brokerCondSet.Manage(bs).MarkTrue(BrokerConditionIngress) + } else { + bs.MarkIngressFailed("EndpointsUnavailable", "Endpoints %q are unavailable.", ep.Name) + } +} + +func (bs *BrokerStatus) MarkTriggerChannelFailed(reason, format string, args ...interface{}) { + brokerCondSet.Manage(bs).MarkFalse(BrokerConditionTriggerChannel, reason, format, args...) +} + +func (bs *BrokerStatus) PropagateTriggerChannelReadiness(cs *duckv1.ChannelableStatus) { + // TODO: Once you can get a Ready status from Channelable in a generic way, use it here... + address := cs.AddressStatus.Address + if address != nil { + brokerCondSet.Manage(bs).MarkTrue(BrokerConditionTriggerChannel) + } else { + bs.MarkTriggerChannelFailed("ChannelNotReady", "trigger Channel is not ready: not addressable") + } +} + +func (bs *BrokerStatus) MarkFilterFailed(reason, format string, args ...interface{}) { + brokerCondSet.Manage(bs).MarkFalse(BrokerConditionFilter, reason, format, args...) +} + +func (bs *BrokerStatus) PropagateFilterAvailability(ep *corev1.Endpoints) { + if duck.EndpointsAreAvailable(ep) { + brokerCondSet.Manage(bs).MarkTrue(BrokerConditionFilter) + } else { + bs.MarkFilterFailed("EndpointsUnavailable", "Endpoints %q are unavailable.", ep.Name) + } +} diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_types.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_types.go new file mode 100644 index 0000000000..0fc1b1177d --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_types.go @@ -0,0 +1,119 @@ +/* + * Copyright 2020 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 v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + + eventingduckv1 "knative.dev/eventing/pkg/apis/duck/v1" + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" + "knative.dev/pkg/kmeta" +) + +// +genclient +// +genreconciler:class=eventing.knative.dev/broker.class,krshapedlogic=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Broker collects a pool of events that are consumable using Triggers. Brokers +// provide a well-known endpoint for event delivery that senders can use with +// minimal knowledge of the event routing strategy. Receivers use Triggers to +// request delivery of events from a Broker's pool to a specific URL or +// Addressable endpoint. +type Broker struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of the Broker. + Spec BrokerSpec `json:"spec,omitempty"` + + // Status represents the current state of the Broker. This data may be out of + // date. + // +optional + Status BrokerStatus `json:"status,omitempty"` +} + +var ( + // Check that Broker can be validated, can be defaulted, and has immutable fields. + _ apis.Validatable = (*Broker)(nil) + _ apis.Defaultable = (*Broker)(nil) + + // Check that Broker can return its spec untyped. + _ apis.HasSpec = (*Broker)(nil) + + _ runtime.Object = (*Broker)(nil) + + // Check that we can create OwnerReferences to a Broker. + _ kmeta.OwnerRefable = (*Broker)(nil) + + // Check that the type conforms to the duck Knative Resource shape. + _ duckv1.KRShaped = (*Broker)(nil) +) + +type BrokerSpec struct { + // Config is a KReference to the configuration that specifies + // configuration options for this Broker. For example, this could be + // a pointer to a ConfigMap. + // +optional + Config *duckv1.KReference `json:"config,omitempty"` + + // Delivery is the delivery specification for Events within the Broker mesh. + // This includes things like retries, DLQ, etc. + // +optional + Delivery *eventingduckv1.DeliverySpec `json:"delivery,omitempty"` +} + +// BrokerStatus represents the current state of a Broker. +type BrokerStatus struct { + // inherits duck/v1 Status, which currently provides: + // * ObservedGeneration - the 'Generation' of the Broker that was last processed by the controller. + // * Conditions - the latest available observations of a resource's current state. + duckv1.Status `json:",inline"` + + // Broker is Addressable. It exposes the endpoint as an URI to get events + // delivered into the Broker mesh. + Address duckv1.Addressable `json:"address,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// BrokerList is a collection of Brokers. +type BrokerList struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + + Items []Broker `json:"items"` +} + +// GetGroupVersionKind returns GroupVersionKind for Brokers +func (t *Broker) GetGroupVersionKind() schema.GroupVersionKind { + return SchemeGroupVersion.WithKind("Broker") +} + +// GetUntypedSpec returns the spec of the Broker. +func (b *Broker) GetUntypedSpec() interface{} { + return b.Spec +} + +// GetStatus retrieves the status of the Broker. Implements the KRShaped interface. +func (t *Broker) GetStatus() *duckv1.Status { + return &t.Status.Status +} diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_validation.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_validation.go new file mode 100644 index 0000000000..e7e0e8a3c4 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_validation.go @@ -0,0 +1,76 @@ +/* +Copyright 2020 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 v1 + +import ( + "context" + + "knative.dev/pkg/apis" + "knative.dev/pkg/kmp" +) + +const ( + BrokerClassAnnotationKey = "eventing.knative.dev/broker.class" +) + +func (b *Broker) Validate(ctx context.Context) *apis.FieldError { + withNS := apis.AllowDifferentNamespace(apis.WithinParent(ctx, b.ObjectMeta)) + return b.Spec.Validate(withNS).ViaField("spec") +} + +func (bs *BrokerSpec) Validate(ctx context.Context) *apis.FieldError { + var errs *apis.FieldError + + // Validate the Config + if bs.Config != nil { + if ce := bs.Config.Validate(ctx); ce != nil { + errs = errs.Also(ce.ViaField("config")) + } + } + + if bs.Delivery != nil { + if de := bs.Delivery.Validate(ctx); de != nil { + errs = errs.Also(de.ViaField("delivery")) + } + } + return errs +} + +func (b *Broker) CheckImmutableFields(ctx context.Context, original *Broker) *apis.FieldError { + if original == nil { + return nil + } + + // Make sure you can't change the class annotation. + diff, err := kmp.ShortDiff(original.GetAnnotations()[BrokerClassAnnotationKey], b.GetAnnotations()[BrokerClassAnnotationKey]) + + if err != nil { + return &apis.FieldError{ + Message: "couldn't diff the Broker objects", + Details: err.Error(), + } + } + + if diff != "" { + return &apis.FieldError{ + Message: "Immutable fields changed (-old +new)", + Paths: []string{"annotations"}, + Details: diff, + } + } + return nil +} diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/doc.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/doc.go new file mode 100644 index 0000000000..312443ded7 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/doc.go @@ -0,0 +1,20 @@ +/* + * Copyright 2020 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 v1 is the v1 version of the API. +// +k8s:deepcopy-gen=package +// +groupName=eventing.knative.dev +package v1 diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/register.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/register.go new file mode 100644 index 0000000000..0ff47f32ff --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/register.go @@ -0,0 +1,55 @@ +/* + * Copyright 2020 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 v1 + +import ( + "knative.dev/eventing/pkg/apis/eventing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: eventing.GroupName, Version: "v1"} + +// Kind takes an unqualified kind and returns back a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &Broker{}, + &BrokerList{}, + &Trigger{}, + &TriggerList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/test_helper.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/test_helper.go new file mode 100644 index 0000000000..64e8d112c7 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/test_helper.go @@ -0,0 +1,122 @@ +/* + * Copyright 2020 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 v1 + +import ( + corev1 "k8s.io/api/core/v1" + + eventingduckv1 "knative.dev/eventing/pkg/apis/duck/v1" + messagingv1beta1 "knative.dev/eventing/pkg/apis/messaging/v1beta1" + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +type testHelper struct{} + +// TestHelper contains helpers for unit tests. +var TestHelper = testHelper{} + +func (testHelper) ReadySubscriptionCondition() *apis.Condition { + return &apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionTrue, + Severity: apis.ConditionSeverityError, + } +} + +func (testHelper) FalseSubscriptionCondition() *apis.Condition { + return &apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionFalse, + Severity: apis.ConditionSeverityError, + Message: "test induced failure condition", + } +} + +func (testHelper) ReadySubscriptionStatus() *messagingv1beta1.SubscriptionStatus { + ss := &messagingv1beta1.SubscriptionStatus{} + ss.MarkChannelReady() + ss.MarkReferencesResolved() + ss.MarkAddedToChannel() + return ss +} + +func (t testHelper) ReadyBrokerStatus() *BrokerStatus { + bs := &BrokerStatus{} + bs.PropagateIngressAvailability(t.AvailableEndpoints()) + bs.PropagateTriggerChannelReadiness(t.ReadyChannelStatus()) + bs.PropagateFilterAvailability(t.AvailableEndpoints()) + bs.SetAddress(apis.HTTP("example.com")) + return bs +} + +func (testHelper) ReadyBrokerCondition() *apis.Condition { + return &apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionTrue, + Severity: apis.ConditionSeverityError, + } +} + +func (testHelper) UnknownBrokerStatus() *BrokerStatus { + bs := &BrokerStatus{} + return bs +} + +func (testHelper) FalseBrokerStatus() *BrokerStatus { + bs := &BrokerStatus{} + bs.SetAddress(nil) + return bs +} + +func (testHelper) UnavailableEndpoints() *corev1.Endpoints { + ep := &corev1.Endpoints{} + ep.Name = "unavailable" + ep.Subsets = []corev1.EndpointSubset{{ + NotReadyAddresses: []corev1.EndpointAddress{{ + IP: "127.0.0.1", + }}, + }} + return ep +} + +func (testHelper) AvailableEndpoints() *corev1.Endpoints { + ep := &corev1.Endpoints{} + ep.Name = "available" + ep.Subsets = []corev1.EndpointSubset{{ + Addresses: []corev1.EndpointAddress{{ + IP: "127.0.0.1", + }}, + }} + return ep +} + +func (testHelper) ReadyChannelStatus() *eventingduckv1.ChannelableStatus { + cs := &eventingduckv1.ChannelableStatus{ + Status: duckv1.Status{}, + AddressStatus: duckv1.AddressStatus{ + Address: &duckv1.Addressable{ + URL: &apis.URL{Scheme: "http", Host: "foo"}, + }, + }, + SubscribableStatus: eventingduckv1.SubscribableStatus{}} + return cs +} + +func (t testHelper) NotReadyChannelStatus() *eventingduckv1.ChannelableStatus { + return &eventingduckv1.ChannelableStatus{} +} diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_conversion.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_conversion.go new file mode 100644 index 0000000000..0df6b92555 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_conversion.go @@ -0,0 +1,34 @@ +/* +Copyright 2020 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 v1 + +import ( + "context" + "fmt" + + "knative.dev/pkg/apis" +) + +// ConvertTo implements apis.Convertible +func (source *Trigger) ConvertTo(ctx context.Context, sink apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", sink) +} + +// ConvertFrom implements apis.Convertible +func (sink *Trigger) ConvertFrom(ctx context.Context, source apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", source) +} diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_defaults.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_defaults.go new file mode 100644 index 0000000000..6a2682d70f --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_defaults.go @@ -0,0 +1,52 @@ +/* + * Copyright 2020 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 v1 + +import ( + "context" + + "knative.dev/pkg/apis" +) + +const ( + brokerLabel = "eventing.knative.dev/broker" +) + +func (t *Trigger) SetDefaults(ctx context.Context) { + withNS := apis.WithinParent(ctx, t.ObjectMeta) + t.Spec.SetDefaults(withNS) + setLabels(t) +} + +func (ts *TriggerSpec) SetDefaults(ctx context.Context) { + if ts.Broker == "" { + ts.Broker = "default" + } + // Make a default filter that allows anything. + if ts.Filter == nil { + ts.Filter = &TriggerFilter{} + } + // Default the Subscriber namespace + ts.Subscriber.SetDefaults(ctx) +} + +func setLabels(t *Trigger) { + if len(t.Labels) == 0 { + t.Labels = map[string]string{} + } + t.Labels[brokerLabel] = t.Spec.Broker +} diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_lifecycle.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_lifecycle.go new file mode 100644 index 0000000000..2ad85b219f --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_lifecycle.go @@ -0,0 +1,187 @@ +/* + * Copyright 2020 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 v1 + +import ( + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +var triggerCondSet = apis.NewLivingConditionSet(TriggerConditionBroker, TriggerConditionSubscribed, TriggerConditionDependency, TriggerConditionSubscriberResolved) + +const ( + // TriggerConditionReady has status True when all subconditions below have been set to True. + TriggerConditionReady = apis.ConditionReady + + TriggerConditionBroker apis.ConditionType = "BrokerReady" + + TriggerConditionSubscribed apis.ConditionType = "SubscriptionReady" + + TriggerConditionDependency apis.ConditionType = "DependencyReady" + + TriggerConditionSubscriberResolved apis.ConditionType = "SubscriberResolved" + + // TriggerAnyFilter Constant to represent that we should allow anything. + TriggerAnyFilter = "" +) + +// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface. +func (*Trigger) GetConditionSet() apis.ConditionSet { + return triggerCondSet +} + +// GetGroupVersionKind returns GroupVersionKind for Triggers +func (t *Trigger) GetGroupVersionKind() schema.GroupVersionKind { + return SchemeGroupVersion.WithKind("Trigger") +} + +// GetUntypedSpec returns the spec of the Trigger. +func (t *Trigger) GetUntypedSpec() interface{} { + return t.Spec +} + +// GetCondition returns the condition currently associated with the given type, or nil. +func (ts *TriggerStatus) GetCondition(t apis.ConditionType) *apis.Condition { + return triggerCondSet.Manage(ts).GetCondition(t) +} + +// GetTopLevelCondition returns the top level Condition. +func (ts *TriggerStatus) GetTopLevelCondition() *apis.Condition { + return triggerCondSet.Manage(ts).GetTopLevelCondition() +} + +// IsReady returns true if the resource is ready overall. +func (ts *TriggerStatus) IsReady() bool { + return triggerCondSet.Manage(ts).IsHappy() +} + +// InitializeConditions sets relevant unset conditions to Unknown state. +func (ts *TriggerStatus) InitializeConditions() { + triggerCondSet.Manage(ts).InitializeConditions() +} + +func (ts *TriggerStatus) PropagateBrokerCondition(bc *apis.Condition) { + if bc == nil { + ts.MarkBrokerNotConfigured() + return + } + + switch { + case bc.Status == corev1.ConditionUnknown: + ts.MarkBrokerUnknown(bc.Reason, bc.Message) + case bc.Status == corev1.ConditionTrue: + triggerCondSet.Manage(ts).MarkTrue(TriggerConditionBroker) + case bc.Status == corev1.ConditionFalse: + ts.MarkBrokerFailed(bc.Reason, bc.Message) + default: + ts.MarkBrokerUnknown("BrokerUnknown", "The status of Broker is invalid: %v", bc.Status) + } +} + +func (ts *TriggerStatus) MarkBrokerFailed(reason, messageFormat string, messageA ...interface{}) { + triggerCondSet.Manage(ts).MarkFalse(TriggerConditionBroker, reason, messageFormat, messageA...) +} + +func (ts *TriggerStatus) MarkBrokerUnknown(reason, messageFormat string, messageA ...interface{}) { + triggerCondSet.Manage(ts).MarkUnknown(TriggerConditionBroker, reason, messageFormat, messageA...) +} + +func (ts *TriggerStatus) MarkBrokerNotConfigured() { + triggerCondSet.Manage(ts).MarkUnknown(TriggerConditionBroker, + "BrokerNotConfigured", "Broker has not yet been reconciled.") +} + +func (ts *TriggerStatus) PropagateSubscriptionCondition(sc *apis.Condition) { + if sc == nil { + ts.MarkSubscriptionNotConfigured() + return + } + + switch { + case sc.Status == corev1.ConditionUnknown: + ts.MarkSubscribedUnknown(sc.Reason, sc.Message) + case sc.Status == corev1.ConditionTrue: + triggerCondSet.Manage(ts).MarkTrue(TriggerConditionSubscribed) + case sc.Status == corev1.ConditionFalse: + ts.MarkNotSubscribed(sc.Reason, sc.Message) + default: + ts.MarkSubscribedUnknown("SubscriptionUnknown", "The status of Subscription is invalid: %v", sc.Status) + } +} + +func (ts *TriggerStatus) MarkNotSubscribed(reason, messageFormat string, messageA ...interface{}) { + triggerCondSet.Manage(ts).MarkFalse(TriggerConditionSubscribed, reason, messageFormat, messageA...) +} + +func (ts *TriggerStatus) MarkSubscribedUnknown(reason, messageFormat string, messageA ...interface{}) { + triggerCondSet.Manage(ts).MarkUnknown(TriggerConditionSubscribed, reason, messageFormat, messageA...) +} + +func (ts *TriggerStatus) MarkSubscriptionNotConfigured() { + triggerCondSet.Manage(ts).MarkUnknown(TriggerConditionSubscribed, + "SubscriptionNotConfigured", "Subscription has not yet been reconciled.") +} + +func (ts *TriggerStatus) MarkSubscriberResolvedSucceeded() { + triggerCondSet.Manage(ts).MarkTrue(TriggerConditionSubscriberResolved) +} + +func (ts *TriggerStatus) MarkSubscriberResolvedFailed(reason, messageFormat string, messageA ...interface{}) { + triggerCondSet.Manage(ts).MarkFalse(TriggerConditionSubscriberResolved, reason, messageFormat, messageA...) +} + +func (ts *TriggerStatus) MarkSubscriberResolvedUnknown(reason, messageFormat string, messageA ...interface{}) { + triggerCondSet.Manage(ts).MarkUnknown(TriggerConditionSubscriberResolved, reason, messageFormat, messageA...) +} + +func (ts *TriggerStatus) MarkDependencySucceeded() { + triggerCondSet.Manage(ts).MarkTrue(TriggerConditionDependency) +} + +func (ts *TriggerStatus) MarkDependencyFailed(reason, messageFormat string, messageA ...interface{}) { + triggerCondSet.Manage(ts).MarkFalse(TriggerConditionDependency, reason, messageFormat, messageA...) +} + +func (ts *TriggerStatus) MarkDependencyUnknown(reason, messageFormat string, messageA ...interface{}) { + triggerCondSet.Manage(ts).MarkUnknown(TriggerConditionDependency, reason, messageFormat, messageA...) +} + +func (ts *TriggerStatus) MarkDependencyNotConfigured() { + triggerCondSet.Manage(ts).MarkUnknown(TriggerConditionDependency, + "DependencyNotConfigured", "Dependency has not yet been reconciled.") +} + +func (ts *TriggerStatus) PropagateDependencyStatus(ks *duckv1.KResource) { + kc := ks.Status.GetCondition(apis.ConditionReady) + if kc == nil { + ts.MarkDependencyNotConfigured() + return + } + + switch { + case kc.Status == corev1.ConditionUnknown: + ts.MarkDependencyUnknown(kc.Reason, kc.Message) + case kc.Status == corev1.ConditionTrue: + ts.MarkDependencySucceeded() + case kc.Status == corev1.ConditionFalse: + ts.MarkDependencyFailed(kc.Reason, kc.Message) + default: + ts.MarkDependencyUnknown("DependencyUnknown", "The status of Dependency is invalid: %v", kc.Status) + } +} diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_types.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_types.go new file mode 100644 index 0000000000..ae1005ce40 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_types.go @@ -0,0 +1,130 @@ +/* + * Copyright 2020 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 v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" + "knative.dev/pkg/kmeta" +) + +const ( + // DependencyAnnotation is the annotation key used to mark the sources that the Trigger depends on. + // This will be used when the kn client creates a source and trigger pair for the user such that the trigger only receives events produced by the paired source. + DependencyAnnotation = "knative.dev/dependency" + // InjectionAnnotation is the annotation key used to enable knative eventing injection for a namespace and automatically create a default broker. + // This will be used when the client creates a trigger paired with default broker and the default broker doesn't exist in the namespace + InjectionAnnotation = "knative-eventing-injection" +) + +// +genclient +// +genreconciler:krshapedlogic=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Trigger represents a request to have events delivered to a consumer from a +// Broker's event pool. +type Trigger struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of the Trigger. + Spec TriggerSpec `json:"spec,omitempty"` + + // Status represents the current state of the Trigger. This data may be out of + // date. + // +optional + Status TriggerStatus `json:"status,omitempty"` +} + +var ( + // Check that Trigger can be validated, can be defaulted, and has immutable fields. + _ apis.Validatable = (*Trigger)(nil) + _ apis.Defaultable = (*Trigger)(nil) + + // Check that Trigger can return its spec untyped. + _ apis.HasSpec = (*Trigger)(nil) + + _ runtime.Object = (*Trigger)(nil) + + // Check that we can create OwnerReferences to a Trigger. + _ kmeta.OwnerRefable = (*Trigger)(nil) + + // Check that the type conforms to the duck Knative Resource shape. + _ duckv1.KRShaped = (*Trigger)(nil) +) + +type TriggerSpec struct { + // Broker is the broker that this trigger receives events from. If not specified, will default + // to 'default'. + Broker string `json:"broker,omitempty"` + + // Filter is the filter to apply against all events from the Broker. Only events that pass this + // filter will be sent to the Subscriber. If not specified, will default to allowing all events. + // + // +optional + Filter *TriggerFilter `json:"filter,omitempty"` + + // Subscriber is the addressable that receives events from the Broker that pass the Filter. It + // is required. + Subscriber duckv1.Destination `json:"subscriber"` +} + +type TriggerFilter struct { + // Attributes filters events by exact match on event context attributes. + // Each key in the map is compared with the equivalent key in the event + // context. An event passes the filter if all values are equal to the + // specified values. + // + // Nested context attributes are not supported as keys. Only string values are supported. + // + // +optional + Attributes TriggerFilterAttributes `json:"attributes,omitempty"` +} + +// TriggerFilterAttributes is a map of context attribute names to values for +// filtering by equality. Only exact matches will pass the filter. You can use the value '' +// to indicate all strings match. +type TriggerFilterAttributes map[string]string + +// TriggerStatus represents the current state of a Trigger. +type TriggerStatus struct { + // inherits duck/v1 Status, which currently provides: + // * ObservedGeneration - the 'Generation' of the Trigger that was last processed by the controller. + // * Conditions - the latest available observations of a resource's current state. + duckv1.Status `json:",inline"` + + // SubscriberURI is the resolved URI of the receiver for this Trigger. + SubscriberURI *apis.URL `json:"subscriberUri,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// TriggerList is a collection of Triggers. +type TriggerList struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + Items []Trigger `json:"items"` +} + +// GetStatus retrieves the status of the Trigger. Implements the KRShaped interface. +func (t *Trigger) GetStatus() *duckv1.Status { + return &t.Status.Status +} diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_validation.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_validation.go new file mode 100644 index 0000000000..8a18a89e18 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/trigger_validation.go @@ -0,0 +1,155 @@ +/* + * Copyright 2020 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 v1 + +import ( + "context" + "encoding/json" + "fmt" + "regexp" + + "knative.dev/pkg/apis" + "knative.dev/pkg/kmp" + + corev1 "k8s.io/api/core/v1" +) + +var ( + // Only allow lowercase alphanumeric, starting with letters. + validAttributeName = regexp.MustCompile(`^[a-z][a-z0-9]*$`) +) + +// Validate the Trigger. +func (t *Trigger) Validate(ctx context.Context) *apis.FieldError { + errs := t.Spec.Validate(ctx).ViaField("spec") + errs = t.validateAnnotation(errs, DependencyAnnotation, t.validateDependencyAnnotation) + errs = t.validateAnnotation(errs, InjectionAnnotation, t.validateInjectionAnnotation) + return errs +} + +// Validate the TriggerSpec. +func (ts *TriggerSpec) Validate(ctx context.Context) *apis.FieldError { + var errs *apis.FieldError + if ts.Broker == "" { + fe := apis.ErrMissingField("broker") + errs = errs.Also(fe) + } + + if ts.Filter != nil { + for attr := range map[string]string(ts.Filter.Attributes) { + if !validAttributeName.MatchString(attr) { + fe := &apis.FieldError{ + Message: fmt.Sprintf("Invalid attribute name: %q", attr), + Paths: []string{"filter.attributes"}, + } + errs = errs.Also(fe) + } + } + } + + if fe := ts.Subscriber.Validate(ctx); fe != nil { + errs = errs.Also(fe.ViaField("subscriber")) + } + + return errs +} + +// CheckImmutableFields checks that any immutable fields were not changed. +func (t *Trigger) CheckImmutableFields(ctx context.Context, original *Trigger) *apis.FieldError { + if original == nil { + return nil + } + + if diff, err := kmp.ShortDiff(original.Spec.Broker, t.Spec.Broker); err != nil { + return &apis.FieldError{ + Message: "Failed to diff Trigger", + Paths: []string{"spec"}, + Details: err.Error(), + } + } else if diff != "" { + return &apis.FieldError{ + Message: "Immutable fields changed (-old +new)", + Paths: []string{"spec", "broker"}, + Details: diff, + } + } + return nil +} + +func GetObjRefFromDependencyAnnotation(dependencyAnnotation string) (corev1.ObjectReference, error) { + var objectRef corev1.ObjectReference + if err := json.Unmarshal([]byte(dependencyAnnotation), &objectRef); err != nil { + return objectRef, err + } + return objectRef, nil +} + +func (t *Trigger) validateAnnotation(errs *apis.FieldError, annotation string, function func(string) *apis.FieldError) *apis.FieldError { + if annotationValue, ok := t.GetAnnotations()[annotation]; ok { + annotationPrefix := fmt.Sprintf("metadata.annotations[%s]", annotation) + errs = errs.Also(function(annotationValue).ViaField(annotationPrefix)) + } + return errs +} + +func (t *Trigger) validateDependencyAnnotation(dependencyAnnotation string) *apis.FieldError { + depObjRef, err := GetObjRefFromDependencyAnnotation(dependencyAnnotation) + if err != nil { + return &apis.FieldError{ + Message: fmt.Sprintf("The provided annotation was not a corev1.ObjectReference: %q", dependencyAnnotation), + Details: err.Error(), + Paths: []string{""}, + } + } + var errs *apis.FieldError + if depObjRef.Namespace != "" && depObjRef.Namespace != t.GetNamespace() { + fe := &apis.FieldError{ + Message: fmt.Sprintf("Namespace must be empty or equal to the trigger namespace %q", t.GetNamespace()), + Paths: []string{"namespace"}, + } + errs = errs.Also(fe) + } + if depObjRef.Kind == "" { + fe := apis.ErrMissingField("kind") + errs = errs.Also(fe) + } + if depObjRef.Name == "" { + fe := apis.ErrMissingField("name") + errs = errs.Also(fe) + } + if depObjRef.APIVersion == "" { + fe := apis.ErrMissingField("apiVersion") + errs = errs.Also(fe) + } + return errs +} + +func (t *Trigger) validateInjectionAnnotation(injectionAnnotation string) *apis.FieldError { + if injectionAnnotation != "enabled" { + return &apis.FieldError{ + Message: fmt.Sprintf(`The provided injection annotation value can only be "enabled", not %q`, injectionAnnotation), + Paths: []string{""}, + } + } + if t.Spec.Broker != "default" { + return &apis.FieldError{ + Message: fmt.Sprintf("The provided injection annotation is only used for default broker, but non-default broker specified here: %q", t.Spec.Broker), + Paths: []string{""}, + } + } + return nil +} diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/zz_generated.deepcopy.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..41b8f75e6d --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/zz_generated.deepcopy.go @@ -0,0 +1,283 @@ +// +build !ignore_autogenerated + +/* +Copyright 2020 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. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" + apisduckv1 "knative.dev/eventing/pkg/apis/duck/v1" + apis "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Broker) DeepCopyInto(out *Broker) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Broker. +func (in *Broker) DeepCopy() *Broker { + if in == nil { + return nil + } + out := new(Broker) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Broker) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BrokerList) DeepCopyInto(out *BrokerList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Broker, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BrokerList. +func (in *BrokerList) DeepCopy() *BrokerList { + if in == nil { + return nil + } + out := new(BrokerList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BrokerList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BrokerSpec) DeepCopyInto(out *BrokerSpec) { + *out = *in + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = new(duckv1.KReference) + **out = **in + } + if in.Delivery != nil { + in, out := &in.Delivery, &out.Delivery + *out = new(apisduckv1.DeliverySpec) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BrokerSpec. +func (in *BrokerSpec) DeepCopy() *BrokerSpec { + if in == nil { + return nil + } + out := new(BrokerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BrokerStatus) DeepCopyInto(out *BrokerStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + in.Address.DeepCopyInto(&out.Address) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BrokerStatus. +func (in *BrokerStatus) DeepCopy() *BrokerStatus { + if in == nil { + return nil + } + out := new(BrokerStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Trigger) DeepCopyInto(out *Trigger) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Trigger. +func (in *Trigger) DeepCopy() *Trigger { + if in == nil { + return nil + } + out := new(Trigger) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Trigger) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TriggerFilter) DeepCopyInto(out *TriggerFilter) { + *out = *in + if in.Attributes != nil { + in, out := &in.Attributes, &out.Attributes + *out = make(TriggerFilterAttributes, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TriggerFilter. +func (in *TriggerFilter) DeepCopy() *TriggerFilter { + if in == nil { + return nil + } + out := new(TriggerFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in TriggerFilterAttributes) DeepCopyInto(out *TriggerFilterAttributes) { + { + in := &in + *out = make(TriggerFilterAttributes, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + return + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TriggerFilterAttributes. +func (in TriggerFilterAttributes) DeepCopy() TriggerFilterAttributes { + if in == nil { + return nil + } + out := new(TriggerFilterAttributes) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TriggerList) DeepCopyInto(out *TriggerList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Trigger, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TriggerList. +func (in *TriggerList) DeepCopy() *TriggerList { + if in == nil { + return nil + } + out := new(TriggerList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TriggerList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TriggerSpec) DeepCopyInto(out *TriggerSpec) { + *out = *in + if in.Filter != nil { + in, out := &in.Filter, &out.Filter + *out = new(TriggerFilter) + (*in).DeepCopyInto(*out) + } + in.Subscriber.DeepCopyInto(&out.Subscriber) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TriggerSpec. +func (in *TriggerSpec) DeepCopy() *TriggerSpec { + if in == nil { + return nil + } + out := new(TriggerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TriggerStatus) DeepCopyInto(out *TriggerStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + if in.SubscriberURI != nil { + in, out := &in.SubscriberURI, &out.SubscriberURI + *out = new(apis.URL) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TriggerStatus. +func (in *TriggerStatus) DeepCopy() *TriggerStatus { + if in == nil { + return nil + } + out := new(TriggerStatus) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1beta1/broker_conversion.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1beta1/broker_conversion.go index f0c61ca95c..8f1cd7c9e6 100644 --- a/vendor/knative.dev/eventing/pkg/apis/eventing/v1beta1/broker_conversion.go +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1beta1/broker_conversion.go @@ -20,15 +20,38 @@ import ( "context" "fmt" + v1 "knative.dev/eventing/pkg/apis/eventing/v1" "knative.dev/pkg/apis" ) // ConvertTo implements apis.Convertible -func (source *Broker) ConvertTo(ctx context.Context, sink apis.Convertible) error { - return fmt.Errorf("v1beta1 is the highest known version, got: %T", sink) +func (source *Broker) ConvertTo(ctx context.Context, to apis.Convertible) error { + switch sink := to.(type) { + case *v1.Broker: + sink.Spec.Config = source.Spec.Config + if err := source.Spec.Delivery.ConvertTo(ctx, sink.Spec.Delivery); err != nil { + return err + } + sink.Status.Status = source.Status.Status + sink.Status.Address = source.Status.Address + return nil + default: + return fmt.Errorf("unknown version, got: %T", sink) + } } // ConvertFrom implements apis.Convertible -func (sink *Broker) ConvertFrom(ctx context.Context, source apis.Convertible) error { - return fmt.Errorf("v1beta1 is the highest known version, got: %T", source) +func (sink *Broker) ConvertFrom(ctx context.Context, from apis.Convertible) error { + switch source := from.(type) { + case *v1.Broker: + sink.Spec.Config = source.Spec.Config + if err := source.Spec.Delivery.ConvertFrom(ctx, sink.Spec.Delivery); err != nil { + return err + } + sink.Status.Status = source.Status.Status + sink.Status.Address = source.Status.Address + return nil + default: + return fmt.Errorf("unknown version, got: %T", source) + } } diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1beta1/eventtype_conversion.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1beta1/eventtype_conversion.go index 6ef342c873..011a013eea 100644 --- a/vendor/knative.dev/eventing/pkg/apis/eventing/v1beta1/eventtype_conversion.go +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1beta1/eventtype_conversion.go @@ -24,11 +24,11 @@ import ( ) // ConvertTo implements apis.Convertible -func (source *EventType) ConvertTo(ctx context.Context, sink apis.Convertible) error { - return fmt.Errorf("v1beta1 is the highest known version, got: %T", sink) +func (source *EventType) ConvertTo(ctx context.Context, to apis.Convertible) error { + return fmt.Errorf("v1beta1 is the highest known version, got: %T", to) } // ConvertFrom implements apis.Convertible -func (sink *EventType) ConvertFrom(ctx context.Context, source apis.Convertible) error { - return fmt.Errorf("v1beta1 is the highest known version, got: %T", source) +func (sink *EventType) ConvertFrom(ctx context.Context, from apis.Convertible) error { + return fmt.Errorf("v1beta1 is the highest known version, got: %T", from) } diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1beta1/trigger_conversion.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1beta1/trigger_conversion.go index dc96d461d1..455b492926 100644 --- a/vendor/knative.dev/eventing/pkg/apis/eventing/v1beta1/trigger_conversion.go +++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1beta1/trigger_conversion.go @@ -20,15 +20,46 @@ import ( "context" "fmt" + v1 "knative.dev/eventing/pkg/apis/eventing/v1" "knative.dev/pkg/apis" ) // ConvertTo implements apis.Convertible -func (source *Trigger) ConvertTo(ctx context.Context, sink apis.Convertible) error { - return fmt.Errorf("v1beta1 is the highest known version, got: %T", sink) +func (source *Trigger) ConvertTo(ctx context.Context, to apis.Convertible) error { + switch sink := to.(type) { + case *v1.Trigger: + sink.Spec.Broker = source.Spec.Broker + sink.Spec.Subscriber = source.Spec.Subscriber + if source.Spec.Filter != nil { + sink.Spec.Filter = &v1.TriggerFilter{} + } + for k, v := range source.Spec.Filter.Attributes { + sink.Spec.Filter.Attributes[k] = v + } + sink.Status.Status = source.Status.Status + sink.Status.SubscriberURI = source.Status.SubscriberURI + return nil + default: + return fmt.Errorf("unknown version, got: %T", sink) + } } // ConvertFrom implements apis.Convertible -func (sink *Trigger) ConvertFrom(ctx context.Context, source apis.Convertible) error { - return fmt.Errorf("v1beta1 is the highest known version, got: %T", source) +func (sink *Trigger) ConvertFrom(ctx context.Context, from apis.Convertible) error { + switch source := from.(type) { + case *v1.Trigger: + sink.Spec.Broker = source.Spec.Broker + sink.Spec.Subscriber = source.Spec.Subscriber + if source.Spec.Filter != nil { + sink.Spec.Filter = &TriggerFilter{} + } + for k, v := range source.Spec.Filter.Attributes { + sink.Spec.Filter.Attributes[k] = v + } + sink.Status.Status = source.Status.Status + sink.Status.SubscriberURI = source.Status.SubscriberURI + return nil + default: + return fmt.Errorf("unknown version, got: %T", source) + } } diff --git a/vendor/knative.dev/eventing/pkg/apis/sources/v1alpha1/ping_types.go b/vendor/knative.dev/eventing/pkg/apis/sources/v1alpha1/ping_types.go index 578c792a83..8068d2d874 100644 --- a/vendor/knative.dev/eventing/pkg/apis/sources/v1alpha1/ping_types.go +++ b/vendor/knative.dev/eventing/pkg/apis/sources/v1alpha1/ping_types.go @@ -26,7 +26,6 @@ import ( ) // +genclient -// +genreconciler // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +k8s:defaulter-gen=true diff --git a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/clientset.go b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/clientset.go index 7b5f994fcd..21897073e1 100644 --- a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/clientset.go +++ b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/clientset.go @@ -25,6 +25,7 @@ import ( rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" configsv1alpha1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/configs/v1alpha1" + eventingv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1" eventingv1beta1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1beta1" flowsv1beta1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/flows/v1beta1" messagingv1beta1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/messaging/v1beta1" @@ -36,6 +37,7 @@ type Interface interface { Discovery() discovery.DiscoveryInterface ConfigsV1alpha1() configsv1alpha1.ConfigsV1alpha1Interface EventingV1beta1() eventingv1beta1.EventingV1beta1Interface + EventingV1() eventingv1.EventingV1Interface FlowsV1beta1() flowsv1beta1.FlowsV1beta1Interface MessagingV1beta1() messagingv1beta1.MessagingV1beta1Interface SourcesV1alpha1() sourcesv1alpha1.SourcesV1alpha1Interface @@ -48,6 +50,7 @@ type Clientset struct { *discovery.DiscoveryClient configsV1alpha1 *configsv1alpha1.ConfigsV1alpha1Client eventingV1beta1 *eventingv1beta1.EventingV1beta1Client + eventingV1 *eventingv1.EventingV1Client flowsV1beta1 *flowsv1beta1.FlowsV1beta1Client messagingV1beta1 *messagingv1beta1.MessagingV1beta1Client sourcesV1alpha1 *sourcesv1alpha1.SourcesV1alpha1Client @@ -64,6 +67,11 @@ func (c *Clientset) EventingV1beta1() eventingv1beta1.EventingV1beta1Interface { return c.eventingV1beta1 } +// EventingV1 retrieves the EventingV1Client +func (c *Clientset) EventingV1() eventingv1.EventingV1Interface { + return c.eventingV1 +} + // FlowsV1beta1 retrieves the FlowsV1beta1Client func (c *Clientset) FlowsV1beta1() flowsv1beta1.FlowsV1beta1Interface { return c.flowsV1beta1 @@ -113,6 +121,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { if err != nil { return nil, err } + cs.eventingV1, err = eventingv1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } cs.flowsV1beta1, err = flowsv1beta1.NewForConfig(&configShallowCopy) if err != nil { return nil, err @@ -143,6 +155,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { var cs Clientset cs.configsV1alpha1 = configsv1alpha1.NewForConfigOrDie(c) cs.eventingV1beta1 = eventingv1beta1.NewForConfigOrDie(c) + cs.eventingV1 = eventingv1.NewForConfigOrDie(c) cs.flowsV1beta1 = flowsv1beta1.NewForConfigOrDie(c) cs.messagingV1beta1 = messagingv1beta1.NewForConfigOrDie(c) cs.sourcesV1alpha1 = sourcesv1alpha1.NewForConfigOrDie(c) @@ -157,6 +170,7 @@ func New(c rest.Interface) *Clientset { var cs Clientset cs.configsV1alpha1 = configsv1alpha1.New(c) cs.eventingV1beta1 = eventingv1beta1.New(c) + cs.eventingV1 = eventingv1.New(c) cs.flowsV1beta1 = flowsv1beta1.New(c) cs.messagingV1beta1 = messagingv1beta1.New(c) cs.sourcesV1alpha1 = sourcesv1alpha1.New(c) diff --git a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/fake/clientset_generated.go b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/fake/clientset_generated.go index 5f55ecc909..a3c066cafe 100644 --- a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -27,6 +27,8 @@ import ( clientset "knative.dev/eventing/pkg/client/clientset/versioned" configsv1alpha1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/configs/v1alpha1" fakeconfigsv1alpha1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/configs/v1alpha1/fake" + eventingv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1" + fakeeventingv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake" eventingv1beta1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1beta1" fakeeventingv1beta1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1beta1/fake" flowsv1beta1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/flows/v1beta1" @@ -96,6 +98,11 @@ func (c *Clientset) EventingV1beta1() eventingv1beta1.EventingV1beta1Interface { return &fakeeventingv1beta1.FakeEventingV1beta1{Fake: &c.Fake} } +// EventingV1 retrieves the EventingV1Client +func (c *Clientset) EventingV1() eventingv1.EventingV1Interface { + return &fakeeventingv1.FakeEventingV1{Fake: &c.Fake} +} + // FlowsV1beta1 retrieves the FlowsV1beta1Client func (c *Clientset) FlowsV1beta1() flowsv1beta1.FlowsV1beta1Interface { return &fakeflowsv1beta1.FakeFlowsV1beta1{Fake: &c.Fake} diff --git a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/fake/register.go b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/fake/register.go index 6b46a004e4..d767c43548 100644 --- a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/fake/register.go +++ b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/fake/register.go @@ -25,6 +25,7 @@ import ( serializer "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" configsv1alpha1 "knative.dev/eventing/pkg/apis/configs/v1alpha1" + eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" eventingv1beta1 "knative.dev/eventing/pkg/apis/eventing/v1beta1" flowsv1beta1 "knative.dev/eventing/pkg/apis/flows/v1beta1" messagingv1beta1 "knative.dev/eventing/pkg/apis/messaging/v1beta1" @@ -38,6 +39,7 @@ var parameterCodec = runtime.NewParameterCodec(scheme) var localSchemeBuilder = runtime.SchemeBuilder{ configsv1alpha1.AddToScheme, eventingv1beta1.AddToScheme, + eventingv1.AddToScheme, flowsv1beta1.AddToScheme, messagingv1beta1.AddToScheme, sourcesv1alpha1.AddToScheme, diff --git a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/scheme/register.go b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/scheme/register.go index 76c104bc5b..a6cb9e4ac2 100644 --- a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/scheme/register.go +++ b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/scheme/register.go @@ -25,6 +25,7 @@ import ( serializer "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" configsv1alpha1 "knative.dev/eventing/pkg/apis/configs/v1alpha1" + eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" eventingv1beta1 "knative.dev/eventing/pkg/apis/eventing/v1beta1" flowsv1beta1 "knative.dev/eventing/pkg/apis/flows/v1beta1" messagingv1beta1 "knative.dev/eventing/pkg/apis/messaging/v1beta1" @@ -38,6 +39,7 @@ var ParameterCodec = runtime.NewParameterCodec(Scheme) var localSchemeBuilder = runtime.SchemeBuilder{ configsv1alpha1.AddToScheme, eventingv1beta1.AddToScheme, + eventingv1.AddToScheme, flowsv1beta1.AddToScheme, messagingv1beta1.AddToScheme, sourcesv1alpha1.AddToScheme, diff --git a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/broker.go b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/broker.go new file mode 100644 index 0000000000..f7309d95a9 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/broker.go @@ -0,0 +1,191 @@ +/* +Copyright 2020 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1 "knative.dev/eventing/pkg/apis/eventing/v1" + scheme "knative.dev/eventing/pkg/client/clientset/versioned/scheme" +) + +// BrokersGetter has a method to return a BrokerInterface. +// A group's client should implement this interface. +type BrokersGetter interface { + Brokers(namespace string) BrokerInterface +} + +// BrokerInterface has methods to work with Broker resources. +type BrokerInterface interface { + Create(*v1.Broker) (*v1.Broker, error) + Update(*v1.Broker) (*v1.Broker, error) + UpdateStatus(*v1.Broker) (*v1.Broker, error) + Delete(name string, options *metav1.DeleteOptions) error + DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error + Get(name string, options metav1.GetOptions) (*v1.Broker, error) + List(opts metav1.ListOptions) (*v1.BrokerList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Broker, err error) + BrokerExpansion +} + +// brokers implements BrokerInterface +type brokers struct { + client rest.Interface + ns string +} + +// newBrokers returns a Brokers +func newBrokers(c *EventingV1Client, namespace string) *brokers { + return &brokers{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the broker, and returns the corresponding broker object, and an error if there is any. +func (c *brokers) Get(name string, options metav1.GetOptions) (result *v1.Broker, err error) { + result = &v1.Broker{} + err = c.client.Get(). + Namespace(c.ns). + Resource("brokers"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Brokers that match those selectors. +func (c *brokers) List(opts metav1.ListOptions) (result *v1.BrokerList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.BrokerList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("brokers"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested brokers. +func (c *brokers) Watch(opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("brokers"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a broker and creates it. Returns the server's representation of the broker, and an error, if there is any. +func (c *brokers) Create(broker *v1.Broker) (result *v1.Broker, err error) { + result = &v1.Broker{} + err = c.client.Post(). + Namespace(c.ns). + Resource("brokers"). + Body(broker). + Do(). + Into(result) + return +} + +// Update takes the representation of a broker and updates it. Returns the server's representation of the broker, and an error, if there is any. +func (c *brokers) Update(broker *v1.Broker) (result *v1.Broker, err error) { + result = &v1.Broker{} + err = c.client.Put(). + Namespace(c.ns). + Resource("brokers"). + Name(broker.Name). + Body(broker). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *brokers) UpdateStatus(broker *v1.Broker) (result *v1.Broker, err error) { + result = &v1.Broker{} + err = c.client.Put(). + Namespace(c.ns). + Resource("brokers"). + Name(broker.Name). + SubResource("status"). + Body(broker). + Do(). + Into(result) + return +} + +// Delete takes name of the broker and deletes it. Returns an error if one occurs. +func (c *brokers) Delete(name string, options *metav1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("brokers"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *brokers) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("brokers"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched broker. +func (c *brokers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Broker, err error) { + result = &v1.Broker{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("brokers"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/doc.go b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/doc.go new file mode 100644 index 0000000000..5b83bd1f41 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2020 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1 diff --git a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/eventing_client.go b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/eventing_client.go new file mode 100644 index 0000000000..c777463401 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/eventing_client.go @@ -0,0 +1,94 @@ +/* +Copyright 2020 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + rest "k8s.io/client-go/rest" + v1 "knative.dev/eventing/pkg/apis/eventing/v1" + "knative.dev/eventing/pkg/client/clientset/versioned/scheme" +) + +type EventingV1Interface interface { + RESTClient() rest.Interface + BrokersGetter + TriggersGetter +} + +// EventingV1Client is used to interact with features provided by the eventing.knative.dev group. +type EventingV1Client struct { + restClient rest.Interface +} + +func (c *EventingV1Client) Brokers(namespace string) BrokerInterface { + return newBrokers(c, namespace) +} + +func (c *EventingV1Client) Triggers(namespace string) TriggerInterface { + return newTriggers(c, namespace) +} + +// NewForConfig creates a new EventingV1Client for the given config. +func NewForConfig(c *rest.Config) (*EventingV1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &EventingV1Client{client}, nil +} + +// NewForConfigOrDie creates a new EventingV1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *EventingV1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new EventingV1Client for the given RESTClient. +func New(c rest.Interface) *EventingV1Client { + return &EventingV1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *EventingV1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/doc.go b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/doc.go new file mode 100644 index 0000000000..c7f6e65cab --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2020 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/fake_broker.go b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/fake_broker.go new file mode 100644 index 0000000000..fff607109c --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/fake_broker.go @@ -0,0 +1,140 @@ +/* +Copyright 2020 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" +) + +// FakeBrokers implements BrokerInterface +type FakeBrokers struct { + Fake *FakeEventingV1 + ns string +} + +var brokersResource = schema.GroupVersionResource{Group: "eventing.knative.dev", Version: "v1", Resource: "brokers"} + +var brokersKind = schema.GroupVersionKind{Group: "eventing.knative.dev", Version: "v1", Kind: "Broker"} + +// Get takes name of the broker, and returns the corresponding broker object, and an error if there is any. +func (c *FakeBrokers) Get(name string, options v1.GetOptions) (result *eventingv1.Broker, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(brokersResource, c.ns, name), &eventingv1.Broker{}) + + if obj == nil { + return nil, err + } + return obj.(*eventingv1.Broker), err +} + +// List takes label and field selectors, and returns the list of Brokers that match those selectors. +func (c *FakeBrokers) List(opts v1.ListOptions) (result *eventingv1.BrokerList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(brokersResource, brokersKind, c.ns, opts), &eventingv1.BrokerList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &eventingv1.BrokerList{ListMeta: obj.(*eventingv1.BrokerList).ListMeta} + for _, item := range obj.(*eventingv1.BrokerList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested brokers. +func (c *FakeBrokers) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(brokersResource, c.ns, opts)) + +} + +// Create takes the representation of a broker and creates it. Returns the server's representation of the broker, and an error, if there is any. +func (c *FakeBrokers) Create(broker *eventingv1.Broker) (result *eventingv1.Broker, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(brokersResource, c.ns, broker), &eventingv1.Broker{}) + + if obj == nil { + return nil, err + } + return obj.(*eventingv1.Broker), err +} + +// Update takes the representation of a broker and updates it. Returns the server's representation of the broker, and an error, if there is any. +func (c *FakeBrokers) Update(broker *eventingv1.Broker) (result *eventingv1.Broker, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(brokersResource, c.ns, broker), &eventingv1.Broker{}) + + if obj == nil { + return nil, err + } + return obj.(*eventingv1.Broker), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeBrokers) UpdateStatus(broker *eventingv1.Broker) (*eventingv1.Broker, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(brokersResource, "status", c.ns, broker), &eventingv1.Broker{}) + + if obj == nil { + return nil, err + } + return obj.(*eventingv1.Broker), err +} + +// Delete takes name of the broker and deletes it. Returns an error if one occurs. +func (c *FakeBrokers) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(brokersResource, c.ns, name), &eventingv1.Broker{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeBrokers) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(brokersResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &eventingv1.BrokerList{}) + return err +} + +// Patch applies the patch and returns the patched broker. +func (c *FakeBrokers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *eventingv1.Broker, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(brokersResource, c.ns, name, pt, data, subresources...), &eventingv1.Broker{}) + + if obj == nil { + return nil, err + } + return obj.(*eventingv1.Broker), err +} diff --git a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/fake_eventing_client.go b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/fake_eventing_client.go new file mode 100644 index 0000000000..4da4be359c --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/fake_eventing_client.go @@ -0,0 +1,44 @@ +/* +Copyright 2020 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + v1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1" +) + +type FakeEventingV1 struct { + *testing.Fake +} + +func (c *FakeEventingV1) Brokers(namespace string) v1.BrokerInterface { + return &FakeBrokers{c, namespace} +} + +func (c *FakeEventingV1) Triggers(namespace string) v1.TriggerInterface { + return &FakeTriggers{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeEventingV1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/fake_trigger.go b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/fake_trigger.go new file mode 100644 index 0000000000..6b3795b6fb --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake/fake_trigger.go @@ -0,0 +1,140 @@ +/* +Copyright 2020 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" +) + +// FakeTriggers implements TriggerInterface +type FakeTriggers struct { + Fake *FakeEventingV1 + ns string +} + +var triggersResource = schema.GroupVersionResource{Group: "eventing.knative.dev", Version: "v1", Resource: "triggers"} + +var triggersKind = schema.GroupVersionKind{Group: "eventing.knative.dev", Version: "v1", Kind: "Trigger"} + +// Get takes name of the trigger, and returns the corresponding trigger object, and an error if there is any. +func (c *FakeTriggers) Get(name string, options v1.GetOptions) (result *eventingv1.Trigger, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(triggersResource, c.ns, name), &eventingv1.Trigger{}) + + if obj == nil { + return nil, err + } + return obj.(*eventingv1.Trigger), err +} + +// List takes label and field selectors, and returns the list of Triggers that match those selectors. +func (c *FakeTriggers) List(opts v1.ListOptions) (result *eventingv1.TriggerList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(triggersResource, triggersKind, c.ns, opts), &eventingv1.TriggerList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &eventingv1.TriggerList{ListMeta: obj.(*eventingv1.TriggerList).ListMeta} + for _, item := range obj.(*eventingv1.TriggerList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested triggers. +func (c *FakeTriggers) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(triggersResource, c.ns, opts)) + +} + +// Create takes the representation of a trigger and creates it. Returns the server's representation of the trigger, and an error, if there is any. +func (c *FakeTriggers) Create(trigger *eventingv1.Trigger) (result *eventingv1.Trigger, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(triggersResource, c.ns, trigger), &eventingv1.Trigger{}) + + if obj == nil { + return nil, err + } + return obj.(*eventingv1.Trigger), err +} + +// Update takes the representation of a trigger and updates it. Returns the server's representation of the trigger, and an error, if there is any. +func (c *FakeTriggers) Update(trigger *eventingv1.Trigger) (result *eventingv1.Trigger, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(triggersResource, c.ns, trigger), &eventingv1.Trigger{}) + + if obj == nil { + return nil, err + } + return obj.(*eventingv1.Trigger), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeTriggers) UpdateStatus(trigger *eventingv1.Trigger) (*eventingv1.Trigger, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(triggersResource, "status", c.ns, trigger), &eventingv1.Trigger{}) + + if obj == nil { + return nil, err + } + return obj.(*eventingv1.Trigger), err +} + +// Delete takes name of the trigger and deletes it. Returns an error if one occurs. +func (c *FakeTriggers) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(triggersResource, c.ns, name), &eventingv1.Trigger{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeTriggers) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(triggersResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &eventingv1.TriggerList{}) + return err +} + +// Patch applies the patch and returns the patched trigger. +func (c *FakeTriggers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *eventingv1.Trigger, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(triggersResource, c.ns, name, pt, data, subresources...), &eventingv1.Trigger{}) + + if obj == nil { + return nil, err + } + return obj.(*eventingv1.Trigger), err +} diff --git a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/generated_expansion.go b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/generated_expansion.go new file mode 100644 index 0000000000..9877b5eba3 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/generated_expansion.go @@ -0,0 +1,23 @@ +/* +Copyright 2020 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +type BrokerExpansion interface{} + +type TriggerExpansion interface{} diff --git a/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/trigger.go b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/trigger.go new file mode 100644 index 0000000000..9726e4e3c8 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/trigger.go @@ -0,0 +1,191 @@ +/* +Copyright 2020 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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1 "knative.dev/eventing/pkg/apis/eventing/v1" + scheme "knative.dev/eventing/pkg/client/clientset/versioned/scheme" +) + +// TriggersGetter has a method to return a TriggerInterface. +// A group's client should implement this interface. +type TriggersGetter interface { + Triggers(namespace string) TriggerInterface +} + +// TriggerInterface has methods to work with Trigger resources. +type TriggerInterface interface { + Create(*v1.Trigger) (*v1.Trigger, error) + Update(*v1.Trigger) (*v1.Trigger, error) + UpdateStatus(*v1.Trigger) (*v1.Trigger, error) + Delete(name string, options *metav1.DeleteOptions) error + DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error + Get(name string, options metav1.GetOptions) (*v1.Trigger, error) + List(opts metav1.ListOptions) (*v1.TriggerList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Trigger, err error) + TriggerExpansion +} + +// triggers implements TriggerInterface +type triggers struct { + client rest.Interface + ns string +} + +// newTriggers returns a Triggers +func newTriggers(c *EventingV1Client, namespace string) *triggers { + return &triggers{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the trigger, and returns the corresponding trigger object, and an error if there is any. +func (c *triggers) Get(name string, options metav1.GetOptions) (result *v1.Trigger, err error) { + result = &v1.Trigger{} + err = c.client.Get(). + Namespace(c.ns). + Resource("triggers"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Triggers that match those selectors. +func (c *triggers) List(opts metav1.ListOptions) (result *v1.TriggerList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.TriggerList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("triggers"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested triggers. +func (c *triggers) Watch(opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("triggers"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a trigger and creates it. Returns the server's representation of the trigger, and an error, if there is any. +func (c *triggers) Create(trigger *v1.Trigger) (result *v1.Trigger, err error) { + result = &v1.Trigger{} + err = c.client.Post(). + Namespace(c.ns). + Resource("triggers"). + Body(trigger). + Do(). + Into(result) + return +} + +// Update takes the representation of a trigger and updates it. Returns the server's representation of the trigger, and an error, if there is any. +func (c *triggers) Update(trigger *v1.Trigger) (result *v1.Trigger, err error) { + result = &v1.Trigger{} + err = c.client.Put(). + Namespace(c.ns). + Resource("triggers"). + Name(trigger.Name). + Body(trigger). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *triggers) UpdateStatus(trigger *v1.Trigger) (result *v1.Trigger, err error) { + result = &v1.Trigger{} + err = c.client.Put(). + Namespace(c.ns). + Resource("triggers"). + Name(trigger.Name). + SubResource("status"). + Body(trigger). + Do(). + Into(result) + return +} + +// Delete takes name of the trigger and deletes it. Returns an error if one occurs. +func (c *triggers) Delete(name string, options *metav1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("triggers"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *triggers) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("triggers"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched trigger. +func (c *triggers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Trigger, err error) { + result = &v1.Trigger{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("triggers"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/interface.go b/vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/interface.go index c4e662bafb..531a3c7721 100644 --- a/vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/interface.go +++ b/vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/interface.go @@ -19,6 +19,7 @@ limitations under the License. package eventing import ( + v1 "knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1" v1beta1 "knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1beta1" internalinterfaces "knative.dev/eventing/pkg/client/informers/externalversions/internalinterfaces" ) @@ -27,6 +28,8 @@ import ( type Interface interface { // V1beta1 provides access to shared informers for resources in V1beta1. V1beta1() v1beta1.Interface + // V1 provides access to shared informers for resources in V1. + V1() v1.Interface } type group struct { @@ -44,3 +47,8 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList func (g *group) V1beta1() v1beta1.Interface { return v1beta1.New(g.factory, g.namespace, g.tweakListOptions) } + +// V1 returns a new v1.Interface. +func (g *group) V1() v1.Interface { + return v1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1/broker.go b/vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1/broker.go new file mode 100644 index 0000000000..b35aa4ee2f --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1/broker.go @@ -0,0 +1,89 @@ +/* +Copyright 2020 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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + time "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" + versioned "knative.dev/eventing/pkg/client/clientset/versioned" + internalinterfaces "knative.dev/eventing/pkg/client/informers/externalversions/internalinterfaces" + v1 "knative.dev/eventing/pkg/client/listers/eventing/v1" +) + +// BrokerInformer provides access to a shared informer and lister for +// Brokers. +type BrokerInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.BrokerLister +} + +type brokerInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewBrokerInformer constructs a new informer for Broker type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewBrokerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredBrokerInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredBrokerInformer constructs a new informer for Broker type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredBrokerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.EventingV1().Brokers(namespace).List(options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.EventingV1().Brokers(namespace).Watch(options) + }, + }, + &eventingv1.Broker{}, + resyncPeriod, + indexers, + ) +} + +func (f *brokerInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredBrokerInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *brokerInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&eventingv1.Broker{}, f.defaultInformer) +} + +func (f *brokerInformer) Lister() v1.BrokerLister { + return v1.NewBrokerLister(f.Informer().GetIndexer()) +} diff --git a/vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1/interface.go b/vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1/interface.go new file mode 100644 index 0000000000..8c36a48dfd --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1/interface.go @@ -0,0 +1,52 @@ +/* +Copyright 2020 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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + internalinterfaces "knative.dev/eventing/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // Brokers returns a BrokerInformer. + Brokers() BrokerInformer + // Triggers returns a TriggerInformer. + Triggers() TriggerInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// Brokers returns a BrokerInformer. +func (v *version) Brokers() BrokerInformer { + return &brokerInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// Triggers returns a TriggerInformer. +func (v *version) Triggers() TriggerInformer { + return &triggerInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1/trigger.go b/vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1/trigger.go new file mode 100644 index 0000000000..6f99981bf7 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1/trigger.go @@ -0,0 +1,89 @@ +/* +Copyright 2020 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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + time "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" + versioned "knative.dev/eventing/pkg/client/clientset/versioned" + internalinterfaces "knative.dev/eventing/pkg/client/informers/externalversions/internalinterfaces" + v1 "knative.dev/eventing/pkg/client/listers/eventing/v1" +) + +// TriggerInformer provides access to a shared informer and lister for +// Triggers. +type TriggerInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.TriggerLister +} + +type triggerInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewTriggerInformer constructs a new informer for Trigger type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewTriggerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredTriggerInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredTriggerInformer constructs a new informer for Trigger type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredTriggerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.EventingV1().Triggers(namespace).List(options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.EventingV1().Triggers(namespace).Watch(options) + }, + }, + &eventingv1.Trigger{}, + resyncPeriod, + indexers, + ) +} + +func (f *triggerInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredTriggerInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *triggerInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&eventingv1.Trigger{}, f.defaultInformer) +} + +func (f *triggerInformer) Lister() v1.TriggerLister { + return v1.NewTriggerLister(f.Informer().GetIndexer()) +} diff --git a/vendor/knative.dev/eventing/pkg/client/informers/externalversions/generic.go b/vendor/knative.dev/eventing/pkg/client/informers/externalversions/generic.go index c91f5c4758..83ba875db8 100644 --- a/vendor/knative.dev/eventing/pkg/client/informers/externalversions/generic.go +++ b/vendor/knative.dev/eventing/pkg/client/informers/externalversions/generic.go @@ -24,6 +24,7 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" v1alpha1 "knative.dev/eventing/pkg/apis/configs/v1alpha1" + v1 "knative.dev/eventing/pkg/apis/eventing/v1" v1beta1 "knative.dev/eventing/pkg/apis/eventing/v1beta1" flowsv1beta1 "knative.dev/eventing/pkg/apis/flows/v1beta1" messagingv1beta1 "knative.dev/eventing/pkg/apis/messaging/v1beta1" @@ -61,6 +62,12 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource case v1alpha1.SchemeGroupVersion.WithResource("configmappropagations"): return &genericInformer{resource: resource.GroupResource(), informer: f.Configs().V1alpha1().ConfigMapPropagations().Informer()}, nil + // Group=eventing.knative.dev, Version=v1 + case v1.SchemeGroupVersion.WithResource("brokers"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Eventing().V1().Brokers().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("triggers"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Eventing().V1().Triggers().Informer()}, nil + // Group=eventing.knative.dev, Version=v1beta1 case v1beta1.SchemeGroupVersion.WithResource("brokers"): return &genericInformer{resource: resource.GroupResource(), informer: f.Eventing().V1beta1().Brokers().Informer()}, nil diff --git a/vendor/knative.dev/eventing/pkg/client/injection/reconciler/eventing/v1beta1/broker/controller.go b/vendor/knative.dev/eventing/pkg/client/injection/reconciler/eventing/v1beta1/broker/controller.go index 861dd414af..002fd8c593 100644 --- a/vendor/knative.dev/eventing/pkg/client/injection/reconciler/eventing/v1beta1/broker/controller.go +++ b/vendor/knative.dev/eventing/pkg/client/injection/reconciler/eventing/v1beta1/broker/controller.go @@ -25,6 +25,8 @@ import ( strings "strings" corev1 "k8s.io/api/core/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" scheme "k8s.io/client-go/kubernetes/scheme" v1 "k8s.io/client-go/kubernetes/typed/core/v1" @@ -35,6 +37,7 @@ import ( kubeclient "knative.dev/pkg/client/injection/kube/client" controller "knative.dev/pkg/controller" logging "knative.dev/pkg/logging" + reconciler "knative.dev/pkg/reconciler" ) const ( @@ -59,9 +62,27 @@ func NewImpl(ctx context.Context, r Interface, classValue string, optionsFns ... brokerInformer := broker.Get(ctx) + lister := brokerInformer.Lister() + rec := &reconcilerImpl{ + LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ + PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { + all, err := lister.List(labels.Everything()) + if err != nil { + return err + } + for _, elt := range all { + // TODO: Consider letting users specify a filter in options. + enq(bkt, types.NamespacedName{ + Namespace: elt.GetNamespace(), + Name: elt.GetName(), + }) + } + return nil + }, + }, Client: client.Get(ctx), - Lister: brokerInformer.Lister(), + Lister: lister, reconciler: r, finalizerName: defaultFinalizerName, classValue: classValue, diff --git a/vendor/knative.dev/eventing/pkg/client/injection/reconciler/eventing/v1beta1/broker/reconciler.go b/vendor/knative.dev/eventing/pkg/client/injection/reconciler/eventing/v1beta1/broker/reconciler.go index 88712aa9b8..83c1c1b9ab 100644 --- a/vendor/knative.dev/eventing/pkg/client/injection/reconciler/eventing/v1beta1/broker/reconciler.go +++ b/vendor/knative.dev/eventing/pkg/client/injection/reconciler/eventing/v1beta1/broker/reconciler.go @@ -29,6 +29,7 @@ import ( equality "k8s.io/apimachinery/pkg/api/equality" errors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" types "k8s.io/apimachinery/pkg/types" sets "k8s.io/apimachinery/pkg/util/sets" cache "k8s.io/client-go/tools/cache" @@ -64,8 +65,30 @@ type Finalizer interface { FinalizeKind(ctx context.Context, o *v1beta1.Broker) reconciler.Event } +// ReadOnlyInterface defines the strongly typed interfaces to be implemented by a +// controller reconciling v1beta1.Broker if they want to process resources for which +// they are not the leader. +type ReadOnlyInterface interface { + // ObserveKind implements logic to observe v1beta1.Broker. + // This method should not write to the API. + ObserveKind(ctx context.Context, o *v1beta1.Broker) reconciler.Event +} + +// ReadOnlyFinalizer defines the strongly typed interfaces to be implemented by a +// controller finalizing v1beta1.Broker if they want to process tombstoned resources +// even when they are not the leader. Due to the nature of how finalizers are handled +// there are no guarantees that this will be called. +type ReadOnlyFinalizer interface { + // ObserveFinalizeKind implements custom logic to observe the final state of v1beta1.Broker. + // This method should not write to the API. + ObserveFinalizeKind(ctx context.Context, o *v1beta1.Broker) reconciler.Event +} + // reconcilerImpl implements controller.Reconciler for v1beta1.Broker resources. type reconcilerImpl struct { + // LeaderAwareFuncs is inlined to help us implement reconciler.LeaderAware + reconciler.LeaderAwareFuncs + // Client is used to write back status updates. Client versioned.Interface @@ -93,13 +116,39 @@ type reconcilerImpl struct { // Check that our Reconciler implements controller.Reconciler var _ controller.Reconciler = (*reconcilerImpl)(nil) +// Check that our generated Reconciler is always LeaderAware. +var _ reconciler.LeaderAware = (*reconcilerImpl)(nil) + func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versioned.Interface, lister eventingv1beta1.BrokerLister, recorder record.EventRecorder, r Interface, classValue string, options ...controller.Options) controller.Reconciler { // Check the options function input. It should be 0 or 1. if len(options) > 1 { logger.Fatalf("up to one options struct is supported, found %d", len(options)) } + // Fail fast when users inadvertently implement the other LeaderAware interface. + // For the typed reconcilers, Promote shouldn't take any arguments. + if _, ok := r.(reconciler.LeaderAware); ok { + logger.Fatalf("%T implements the incorrect LeaderAware interface. Promote() should not take an argument as genreconciler handles the enqueuing automatically.", r) + } + // TODO: Consider validating when folks implement ReadOnlyFinalizer, but not Finalizer. + rec := &reconcilerImpl{ + LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ + PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { + all, err := lister.List(labels.Everything()) + if err != nil { + return err + } + for _, elt := range all { + // TODO: Consider letting users specify a filter in options. + enq(bkt, types.NamespacedName{ + Namespace: elt.GetNamespace(), + Name: elt.GetName(), + }) + } + return nil + }, + }, Client: client, Lister: lister, Recorder: recorder, @@ -124,6 +173,25 @@ func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versio func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { logger := logging.FromContext(ctx) + // Convert the namespace/name string into a distinct namespace and name + namespace, name, err := cache.SplitMetaNamespaceKey(key) + if err != nil { + logger.Errorf("invalid resource key: %s", key) + return nil + } + // Establish whether we are the leader for use below. + isLeader := r.IsLeaderFor(types.NamespacedName{ + Namespace: namespace, + Name: name, + }) + roi, isROI := r.reconciler.(ReadOnlyInterface) + rof, isROF := r.reconciler.(ReadOnlyFinalizer) + if !isLeader && !isROI && !isROF { + // If we are not the leader, and we don't implement either ReadOnly + // interface, then take a fast-path out. + return nil + } + // If configStore is set, attach the frozen configuration to the context. if r.configStore != nil { ctx = r.configStore.ToContext(ctx) @@ -132,15 +200,6 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { // Add the recorder to context. ctx = controller.WithEventRecorder(ctx, r.Recorder) - // Convert the namespace/name string into a distinct namespace and name - - namespace, name, err := cache.SplitMetaNamespaceKey(key) - - if err != nil { - logger.Errorf("invalid resource key: %s", key) - return nil - } - // Get the resource with this namespace/name. getter := r.Lister.Brokers(namespace) @@ -167,24 +226,32 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { var reconcileEvent reconciler.Event if resource.GetDeletionTimestamp().IsZero() { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ReconcileKind")) + if isLeader { + // Append the target method to the logger. + logger = logger.With(zap.String("targetMethod", "ReconcileKind")) + + // Set and update the finalizer on resource if r.reconciler + // implements Finalizer. + if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil { + return fmt.Errorf("failed to set finalizers: %w", err) + } - // Set and update the finalizer on resource if r.reconciler - // implements Finalizer. - if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil { - return fmt.Errorf("failed to set finalizers: %w", err) - } + reconciler.PreProcessReconcile(ctx, resource) - reconciler.PreProcessReconcile(ctx, resource) + // Reconcile this copy of the resource and then write back any status + // updates regardless of whether the reconciliation errored out. + reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) - // Reconcile this copy of the resource and then write back any status - // updates regardless of whether the reconciliation errored out. - reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + reconciler.PostProcessReconcile(ctx, resource, original) - reconciler.PostProcessReconcile(ctx, resource, original) + } else if isROI { + // Append the target method to the logger. + logger = logger.With(zap.String("targetMethod", "ObserveKind")) - } else if fin, ok := r.reconciler.(Finalizer); ok { + // Observe any changes to this resource, since we are not the leader. + reconcileEvent = roi.ObserveKind(ctx, resource) + } + } else if fin, ok := r.reconciler.(Finalizer); isLeader && ok { // Append the target method to the logger. logger = logger.With(zap.String("targetMethod", "FinalizeKind")) @@ -194,6 +261,12 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { if resource, err = r.clearFinalizer(ctx, resource, reconcileEvent); err != nil { return fmt.Errorf("failed to clear finalizers: %w", err) } + } else if !isLeader && isROF { + // Append the target method to the logger. + logger = logger.With(zap.String("targetMethod", "ObserveFinalizeKind")) + + // For finalizing reconcilers, just observe when we aren't the leader. + reconcileEvent = rof.ObserveFinalizeKind(ctx, resource) } // Synchronize the status. @@ -202,6 +275,9 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { // This is important because the copy we loaded from the injectionInformer's // cache may be stale and we don't want to overwrite a prior update // to status with this stale state. + } else if !isLeader { + logger.Warn("Saw status changes when we aren't the leader!") + // TODO: Consider logging the diff at Debug? } else if err = r.updateStatus(original, resource); err != nil { logger.Warnw("Failed to update resource status", zap.Error(err)) r.Recorder.Eventf(resource, v1.EventTypeWarning, "UpdateFailed", diff --git a/vendor/knative.dev/eventing/pkg/client/listers/eventing/v1/broker.go b/vendor/knative.dev/eventing/pkg/client/listers/eventing/v1/broker.go new file mode 100644 index 0000000000..c6dca9da07 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/client/listers/eventing/v1/broker.go @@ -0,0 +1,94 @@ +/* +Copyright 2020 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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1 "knative.dev/eventing/pkg/apis/eventing/v1" +) + +// BrokerLister helps list Brokers. +type BrokerLister interface { + // List lists all Brokers in the indexer. + List(selector labels.Selector) (ret []*v1.Broker, err error) + // Brokers returns an object that can list and get Brokers. + Brokers(namespace string) BrokerNamespaceLister + BrokerListerExpansion +} + +// brokerLister implements the BrokerLister interface. +type brokerLister struct { + indexer cache.Indexer +} + +// NewBrokerLister returns a new BrokerLister. +func NewBrokerLister(indexer cache.Indexer) BrokerLister { + return &brokerLister{indexer: indexer} +} + +// List lists all Brokers in the indexer. +func (s *brokerLister) List(selector labels.Selector) (ret []*v1.Broker, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.Broker)) + }) + return ret, err +} + +// Brokers returns an object that can list and get Brokers. +func (s *brokerLister) Brokers(namespace string) BrokerNamespaceLister { + return brokerNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// BrokerNamespaceLister helps list and get Brokers. +type BrokerNamespaceLister interface { + // List lists all Brokers in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1.Broker, err error) + // Get retrieves the Broker from the indexer for a given namespace and name. + Get(name string) (*v1.Broker, error) + BrokerNamespaceListerExpansion +} + +// brokerNamespaceLister implements the BrokerNamespaceLister +// interface. +type brokerNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Brokers in the indexer for a given namespace. +func (s brokerNamespaceLister) List(selector labels.Selector) (ret []*v1.Broker, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1.Broker)) + }) + return ret, err +} + +// Get retrieves the Broker from the indexer for a given namespace and name. +func (s brokerNamespaceLister) Get(name string) (*v1.Broker, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("broker"), name) + } + return obj.(*v1.Broker), nil +} diff --git a/vendor/knative.dev/eventing/pkg/client/listers/eventing/v1/expansion_generated.go b/vendor/knative.dev/eventing/pkg/client/listers/eventing/v1/expansion_generated.go new file mode 100644 index 0000000000..7a8772ae63 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/client/listers/eventing/v1/expansion_generated.go @@ -0,0 +1,35 @@ +/* +Copyright 2020 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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +// BrokerListerExpansion allows custom methods to be added to +// BrokerLister. +type BrokerListerExpansion interface{} + +// BrokerNamespaceListerExpansion allows custom methods to be added to +// BrokerNamespaceLister. +type BrokerNamespaceListerExpansion interface{} + +// TriggerListerExpansion allows custom methods to be added to +// TriggerLister. +type TriggerListerExpansion interface{} + +// TriggerNamespaceListerExpansion allows custom methods to be added to +// TriggerNamespaceLister. +type TriggerNamespaceListerExpansion interface{} diff --git a/vendor/knative.dev/eventing/pkg/client/listers/eventing/v1/trigger.go b/vendor/knative.dev/eventing/pkg/client/listers/eventing/v1/trigger.go new file mode 100644 index 0000000000..bd362b5c5f --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/client/listers/eventing/v1/trigger.go @@ -0,0 +1,94 @@ +/* +Copyright 2020 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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1 "knative.dev/eventing/pkg/apis/eventing/v1" +) + +// TriggerLister helps list Triggers. +type TriggerLister interface { + // List lists all Triggers in the indexer. + List(selector labels.Selector) (ret []*v1.Trigger, err error) + // Triggers returns an object that can list and get Triggers. + Triggers(namespace string) TriggerNamespaceLister + TriggerListerExpansion +} + +// triggerLister implements the TriggerLister interface. +type triggerLister struct { + indexer cache.Indexer +} + +// NewTriggerLister returns a new TriggerLister. +func NewTriggerLister(indexer cache.Indexer) TriggerLister { + return &triggerLister{indexer: indexer} +} + +// List lists all Triggers in the indexer. +func (s *triggerLister) List(selector labels.Selector) (ret []*v1.Trigger, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.Trigger)) + }) + return ret, err +} + +// Triggers returns an object that can list and get Triggers. +func (s *triggerLister) Triggers(namespace string) TriggerNamespaceLister { + return triggerNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// TriggerNamespaceLister helps list and get Triggers. +type TriggerNamespaceLister interface { + // List lists all Triggers in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1.Trigger, err error) + // Get retrieves the Trigger from the indexer for a given namespace and name. + Get(name string) (*v1.Trigger, error) + TriggerNamespaceListerExpansion +} + +// triggerNamespaceLister implements the TriggerNamespaceLister +// interface. +type triggerNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Triggers in the indexer for a given namespace. +func (s triggerNamespaceLister) List(selector labels.Selector) (ret []*v1.Trigger, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1.Trigger)) + }) + return ret, err +} + +// Get retrieves the Trigger from the indexer for a given namespace and name. +func (s triggerNamespaceLister) Get(name string) (*v1.Trigger, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("trigger"), name) + } + return obj.(*v1.Trigger), nil +} diff --git a/vendor/knative.dev/eventing/test/conformance/helpers/channel_message_modes_specversion_helper.go b/vendor/knative.dev/eventing/test/conformance/helpers/channel_message_modes_specversion_helper.go new file mode 100644 index 0000000000..6c9b7205ef --- /dev/null +++ b/vendor/knative.dev/eventing/test/conformance/helpers/channel_message_modes_specversion_helper.go @@ -0,0 +1,113 @@ +/* +Copyright 2020 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 helpers + +import ( + "strings" + "testing" + + cloudevents "github.com/cloudevents/sdk-go/v2" + . "github.com/cloudevents/sdk-go/v2/test" + "github.com/google/uuid" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + testlib "knative.dev/eventing/test/lib" + "knative.dev/eventing/test/lib/recordevents" + "knative.dev/eventing/test/lib/resources" + "knative.dev/eventing/test/lib/resources/sender" +) + +// ChannelMessageModesAndSpecVersionsTestRunner tests the support of the channel ingress for different spec versions and message modes +func ChannelMessageModesAndSpecVersionsTestRunner( + t *testing.T, + channelTestRunner testlib.ComponentsTestRunner, + options ...testlib.SetupClientOption, +) { + testCases := []struct { + encoding cloudevents.Encoding + version string + }{ + { + encoding: cloudevents.EncodingBinary, + version: cloudevents.VersionV03, + }, { + encoding: cloudevents.EncodingStructured, + version: cloudevents.VersionV03, + }, { + encoding: cloudevents.EncodingBinary, + version: cloudevents.VersionV1, + }, { + encoding: cloudevents.EncodingStructured, + version: cloudevents.VersionV1, + }, + } + + channelTestRunner.RunTests(t, testlib.FeatureBasic, func(t *testing.T, channel metav1.TypeMeta) { + for _, tc := range testCases { + t.Run("encoding_"+tc.encoding.String()+"_version_"+tc.version, func(t *testing.T) { + messageModeSpecVersionTest(t, channel, tc.encoding, tc.version, options...) + }) + } + }) +} + +// Sender -> Channel -> Subscriber -> Record Events +func messageModeSpecVersionTest(t *testing.T, channel metav1.TypeMeta, encoding cloudevents.Encoding, version string, options ...testlib.SetupClientOption) { + client := testlib.Setup(t, true, options...) + defer testlib.TearDown(client) + + resourcesNamePrefix := strings.ReplaceAll(strings.ToLower(encoding.String()+"-"+version), ".", "") + + channelName := resourcesNamePrefix + "-ch" + client.CreateChannelOrFail(channelName, &channel) + + subscriberName := resourcesNamePrefix + "-recordevents" + eventTracker, _ := recordevents.StartEventRecordOrFail(client, subscriberName) + + client.CreateSubscriptionOrFail( + resourcesNamePrefix+"-sub", + channelName, + &channel, + resources.WithSubscriberForSubscription(subscriberName), + ) + + client.WaitForAllTestResourcesReadyOrFail() + + event := FullEvent() + event.SetID(uuid.New().String()) + + switch version { + case cloudevents.VersionV1: + event.Context = event.Context.AsV1() + case cloudevents.VersionV03: + event.Context = event.Context.AsV03() + } + + client.SendEventToAddressable( + resourcesNamePrefix+"-sender", + channelName, + &channel, + event, + sender.WithEncoding(encoding), + ) + + eventTracker.AssertExact(1, recordevents.NoError(), recordevents.MatchEvent( + HasSpecVersion(version), + HasId(event.ID()), + IsValid(), + )) +} diff --git a/vendor/knative.dev/eventing/test/conformance/helpers/source_crd_metadata_test_helper.go b/vendor/knative.dev/eventing/test/conformance/helpers/source_crd_metadata_test_helper.go new file mode 100644 index 0000000000..5cde699acb --- /dev/null +++ b/vendor/knative.dev/eventing/test/conformance/helpers/source_crd_metadata_test_helper.go @@ -0,0 +1,48 @@ +/* +Copyright 2020 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 helpers + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + testlib "knative.dev/eventing/test/lib" +) + +var sourceLabels = map[string]string{ + "duck.knative.dev/source": "true", +} + +func SourceCRDMetadataTestHelperWithChannelTestRunner( + t *testing.T, + sourceTestRunner testlib.ComponentsTestRunner, + options ...testlib.SetupClientOption, +) { + + sourceTestRunner.RunTests(t, testlib.FeatureBasic, func(st *testing.T, source metav1.TypeMeta) { + client := testlib.Setup(st, true, options...) + defer testlib.TearDown(client) + + // From spec: + // Each source MUST have the following: + // label of duck.knative.dev/source: "true" + t.Run("Source CRD has required label", func(t *testing.T) { + validateRequiredLabels(client, source, sourceLabels) + }) + + }) +} diff --git a/vendor/knative.dev/eventing/test/e2e-tests.sh b/vendor/knative.dev/eventing/test/e2e-tests.sh index adb66e808f..3b377ac9c4 100644 --- a/vendor/knative.dev/eventing/test/e2e-tests.sh +++ b/vendor/knative.dev/eventing/test/e2e-tests.sh @@ -35,6 +35,6 @@ initialize $@ --skip-istio-addon install_mt_broker || fail_test "Could not install MT Channel Based Broker" echo "Running tests with Multi Tenant Channel Based Broker" -go_test_e2e -timeout=20m -parallel=12 ./test/e2e ./test/conformance -brokerclass=MTChannelBasedBroker -channels=messaging.knative.dev/v1beta1:Channel,messaging.knative.dev/v1beta1:InMemoryChannel || fail_test +go_test_e2e -timeout=20m -parallel=12 ./test/e2e ./test/conformance -brokerclass=MTChannelBasedBroker -channels=messaging.knative.dev/v1beta1:Channel,messaging.knative.dev/v1beta1:InMemoryChannel -sources=sources.knative.dev/v1alpha2:ApiServerSource,sources.knative.dev/v1alpha2:ContainerSource,sources.knative.dev/v1alpha2:PingSource || fail_test success diff --git a/vendor/knative.dev/eventing/test/e2e_flags.go b/vendor/knative.dev/eventing/test/e2e_flags.go index d67925fc2d..af7b552ffa 100644 --- a/vendor/knative.dev/eventing/test/e2e_flags.go +++ b/vendor/knative.dev/eventing/test/e2e_flags.go @@ -35,6 +35,9 @@ const ( BrokerUsage = "Which brokerclass to test, requires the proper Broker " + "implementation to have been installed, and only one value. brokerclass " + "must be (for now) 'MTChannelBasedBroker'." + SourceUsage = "The names of the source type metas, separated by comma. " + + "Example: \"sources.knative.dev/v1alpha1:ApiServerSource," + + "sources.knative.dev/v1alpha1:PingSource\"." ) // EventingFlags holds the command line flags specific to knative/eventing. @@ -46,6 +49,7 @@ func InitializeEventingFlags() { flag.Var(&EventingFlags.Channels, "channels", ChannelUsage) flag.StringVar(&EventingFlags.BrokerClass, "brokerclass", "MTChannelBasedBroker", BrokerUsage) + flag.Var(&EventingFlags.Sources, "sources", SourceUsage) flag.Parse() // If no channel is passed through the flag, initialize it as the DefaultChannel. diff --git a/vendor/knative.dev/eventing/test/flags/channels.go b/vendor/knative.dev/eventing/test/flags/channels.go index d4ff2cc22b..3cb7a2928f 100644 --- a/vendor/knative.dev/eventing/test/flags/channels.go +++ b/vendor/knative.dev/eventing/test/flags/channels.go @@ -18,7 +18,6 @@ package flags import ( "fmt" - "log" "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -33,26 +32,11 @@ func (channels *Channels) String() string { // Set appends the input string to Channels. func (channels *Channels) Set(value string) error { - for _, channel := range strings.Split(value, ",") { - channel := strings.TrimSpace(channel) - split := strings.Split(channel, ":") - if len(split) != 2 { - log.Fatalf("The given Channel name %q is invalid, it needs to be in the form \"apiVersion:Kind\".", channel) - } - tm := metav1.TypeMeta{ - APIVersion: split[0], - Kind: split[1], - } - if !isValidChannel(tm.Kind) { - log.Fatalf("The given Channel name %q is invalid, tests cannot be run.\n", channel) - } - - *channels = append(*channels, tm) - } + *channels = csvToObjects(value, isValidChannel) return nil } -// Check if the channel name is valid. +// Check if the channel kind is valid. func isValidChannel(channel string) bool { return strings.HasSuffix(channel, "Channel") } diff --git a/vendor/knative.dev/eventing/test/flags/eventing_environment.go b/vendor/knative.dev/eventing/test/flags/eventing_environment.go index b53d3738a0..65a05dd7ac 100644 --- a/vendor/knative.dev/eventing/test/flags/eventing_environment.go +++ b/vendor/knative.dev/eventing/test/flags/eventing_environment.go @@ -20,4 +20,5 @@ package flags type EventingEnvironmentFlags struct { BrokerClass string Channels + Sources } diff --git a/vendor/knative.dev/eventing/test/flags/parsing.go b/vendor/knative.dev/eventing/test/flags/parsing.go new file mode 100644 index 0000000000..6fba018767 --- /dev/null +++ b/vendor/knative.dev/eventing/test/flags/parsing.go @@ -0,0 +1,47 @@ +/* +Copyright 2020 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 flags + +import ( + "log" + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type Validator func(string) bool + +func csvToObjects(csvObjects string, validator Validator) []metav1.TypeMeta { + result := make([]metav1.TypeMeta, 0, 5) + for _, object := range strings.Split(csvObjects, ",") { + object := strings.TrimSpace(object) + split := strings.Split(object, ":") + if len(split) != 2 { + log.Fatalf("The given object name %q is invalid, it needs to be in the form \"apiVersion:Kind\".", object) + } + tm := metav1.TypeMeta{ + APIVersion: split[0], + Kind: split[1], + } + if !validator(tm.Kind) { + log.Fatalf("The given object name %q is invalid, tests cannot be run.\n", object) + } + + result = append(result, tm) + } + return result +} diff --git a/vendor/knative.dev/eventing/test/flags/sources.go b/vendor/knative.dev/eventing/test/flags/sources.go new file mode 100644 index 0000000000..9add5e7b8c --- /dev/null +++ b/vendor/knative.dev/eventing/test/flags/sources.go @@ -0,0 +1,42 @@ +/* +Copyright 2020 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 flags + +import ( + "fmt" + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// Sources holds the Sources we want to run test against. +type Sources []metav1.TypeMeta + +func (sources *Sources) String() string { + return fmt.Sprint(*sources) +} + +// Set appends the input string to Sources. +func (sources *Sources) Set(value string) error { + *sources = csvToObjects(value, isValidSource) + return nil +} + +// Check if the Source kind is valid. +func isValidSource(source string) bool { + return strings.HasSuffix(source, "Source") +} diff --git a/vendor/knative.dev/eventing/test/lib/recordevents/event_info_matchers.go b/vendor/knative.dev/eventing/test/lib/recordevents/event_info_matchers.go index 4444f86565..65d1bef4f0 100644 --- a/vendor/knative.dev/eventing/test/lib/recordevents/event_info_matchers.go +++ b/vendor/knative.dev/eventing/test/lib/recordevents/event_info_matchers.go @@ -46,6 +46,16 @@ func AllOf(matchers ...EventInfoMatcher) EventInfoMatcher { } } +// Matcher that fails if there is an error in the EventInfo +func NoError() EventInfoMatcher { + return func(ei EventInfo) error { + if ei.Error != "" { + return fmt.Errorf("not expecting an error in event info: %s", ei.Error) + } + return nil + } +} + // Convert a matcher that checks valid messages to a function // that checks EventInfo structures, returning an error for any that don't // contain valid events. diff --git a/vendor/knative.dev/eventing/test/lib/recordevents/event_info_store.go b/vendor/knative.dev/eventing/test/lib/recordevents/event_info_store.go index 3a5de9a481..6576936247 100644 --- a/vendor/knative.dev/eventing/test/lib/recordevents/event_info_store.go +++ b/vendor/knative.dev/eventing/test/lib/recordevents/event_info_store.go @@ -185,14 +185,15 @@ func (ei *EventInfoStore) refreshData() ([]EventInfo, error) { return allEvents, nil } -// Find all events received by the recordevents pod that match the provided function, +// Find all events received by the recordevents pod that match the provided matchers, // returning all matching events as well as a SearchedInfo structure including the // last 5 events seen and the total events matched. This SearchedInfo structure // is primarily to ease debugging in failure printouts. The provided function is // guaranteed to be called exactly once on each EventInfo from the pod. // The error array contains the eventual match errors, while the last return error contains // an eventual communication error while trying to get the events from the recordevents pod -func (ei *EventInfoStore) Find(f EventInfoMatcher) ([]EventInfo, SearchedInfo, []error, error) { +func (ei *EventInfoStore) Find(matchers ...EventInfoMatcher) ([]EventInfo, SearchedInfo, []error, error) { + f := AllOf(matchers...) const maxLastEvents = 5 allMatch := []EventInfo{} sInfo := SearchedInfo{} @@ -221,20 +222,20 @@ func (ei *EventInfoStore) Find(f EventInfoMatcher) ([]EventInfo, SearchedInfo, [ return allMatch, sInfo, nonMatchingErrors, nil } -// Assert that there are at least min number of matches of f. +// Assert that there are at least min number of match for the provided matchers. // This method fails the test if the assert is not fulfilled. -func (ei *EventInfoStore) AssertAtLeast(min int, f EventInfoMatcher) []EventInfo { - events, err := ei.waitAtLeastNMatch(f, min) +func (ei *EventInfoStore) AssertAtLeast(min int, matchers ...EventInfoMatcher) []EventInfo { + events, err := ei.waitAtLeastNMatch(AllOf(matchers...), min) if err != nil { ei.tb.Fatalf("Timeout waiting for at least %d matches.\nError: %v", min, errors.WithStack(err)) } return events } -// Assert that there are at least min number of matches and at most max number of matches of f. +// Assert that there are at least min number of matches and at most max number of matches for the provided matchers. // This method fails the test if the assert is not fulfilled. -func (ei *EventInfoStore) AssertInRange(min int, max int, f EventInfoMatcher) []EventInfo { - events := ei.AssertAtLeast(min, f) +func (ei *EventInfoStore) AssertInRange(min int, max int, matchers ...EventInfoMatcher) []EventInfo { + events := ei.AssertAtLeast(min, matchers...) if max > 0 && len(events) > max { ei.tb.Fatalf("Assert in range failed: %v", errors.WithStack(fmt.Errorf("expected <= %d events, saw %d", max, len(events)))) } @@ -242,10 +243,10 @@ func (ei *EventInfoStore) AssertInRange(min int, max int, f EventInfoMatcher) [] return events } -// Assert that there aren't any matches of f. +// Assert that there aren't any matches for the provided matchers. // This method fails the test if the assert is not fulfilled. -func (ei *EventInfoStore) AssertNot(f EventInfoMatcher) []EventInfo { - res, recentEvents, _, err := ei.Find(f) +func (ei *EventInfoStore) AssertNot(matchers ...EventInfoMatcher) []EventInfo { + res, recentEvents, _, err := ei.Find(matchers...) if err != nil { ei.tb.Fatalf("Unexpected error during find on recordevents '%s': %v", ei.podName, errors.WithStack(err)) } @@ -259,10 +260,10 @@ func (ei *EventInfoStore) AssertNot(f EventInfoMatcher) []EventInfo { return res } -// Assert that there are exactly n matches of f. +// Assert that there are exactly n matches for the provided matchers. // This method fails the test if the assert is not fulfilled. -func (ei *EventInfoStore) AssertExact(n int, f EventInfoMatcher) []EventInfo { - return ei.AssertInRange(n, n, f) +func (ei *EventInfoStore) AssertExact(n int, matchers ...EventInfoMatcher) []EventInfo { + return ei.AssertInRange(n, n, matchers...) } // Wait a long time (currently 4 minutes) until the provided function matches at least diff --git a/vendor/knative.dev/pkg/apis/duck/register.go b/vendor/knative.dev/pkg/apis/duck/register.go index d10adc21ce..d84cd49d18 100644 --- a/vendor/knative.dev/pkg/apis/duck/register.go +++ b/vendor/knative.dev/pkg/apis/duck/register.go @@ -18,4 +18,12 @@ package duck const ( GroupName = "duck.knative.dev" + + // AddressableDuckVersionLabel is the label we use to declare + // that a type conforms to the Addressable duck type. + AddressableDuckVersionLabel = "duck.knative.dev/addressable" + + // SourceDuckVersionLabel is the label we use to declare + // that a type conforms to the Source duck type. + SourceDuckVersionLabel = "duck.knative.dev/source" ) diff --git a/vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/packages.go b/vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/packages.go index c54d6f915c..50f3cb4618 100644 --- a/vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/packages.go +++ b/vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/packages.go @@ -201,7 +201,7 @@ func isKRShaped(tags map[string]map[string]string) bool { if !has { return false } - return vals["krshapedlogic"] == "true" + return vals["krshapedlogic"] != "false" } func isNonNamespaced(tags map[string]map[string]string) bool { diff --git a/vendor/knative.dev/pkg/configmap/manual_watcher.go b/vendor/knative.dev/pkg/configmap/manual_watcher.go index ad39bb8b9e..b1eb276339 100644 --- a/vendor/knative.dev/pkg/configmap/manual_watcher.go +++ b/vendor/knative.dev/pkg/configmap/manual_watcher.go @@ -26,9 +26,8 @@ import ( type ManualWatcher struct { Namespace string - // Guards mutations to defaultImpl fields - m sync.RWMutex - + // Guards observers + m sync.RWMutex observers map[string][]Observer } @@ -40,7 +39,7 @@ func (w *ManualWatcher) Watch(name string, o ...Observer) { defer w.m.Unlock() if w.observers == nil { - w.observers = make(map[string][]Observer, len(o)) + w.observers = make(map[string][]Observer, 1) } w.observers[name] = append(w.observers[name], o...) } @@ -58,13 +57,8 @@ func (w *ManualWatcher) OnChange(configMap *corev1.ConfigMap) { // Within our namespace, take the lock and see if there are any registered observers. w.m.RLock() defer w.m.RUnlock() - observers, ok := w.observers[configMap.Name] - if !ok { - return // No observers. - } - // Iterate over the observers and invoke their callbacks. - for _, o := range observers { + for _, o := range w.observers[configMap.Name] { o(configMap) } } diff --git a/vendor/knative.dev/pkg/test/gcs/gcs.go b/vendor/knative.dev/pkg/test/gcs/gcs.go index b2798ac6a5..13ae206fa6 100644 --- a/vendor/knative.dev/pkg/test/gcs/gcs.go +++ b/vendor/knative.dev/pkg/test/gcs/gcs.go @@ -146,9 +146,17 @@ func (g *GCSClient) getObjectsAttrs(ctx context.Context, bucketName, storagePath return allAttrs, nil } +func (g *GCSClient) listChildren(ctx context.Context, bucketName, dirPath, exclusionFilter string) ([]string, error) { + if dirPath != "" { + dirPath = strings.TrimRight(dirPath, " /") + "/" + } + + return g.list(ctx, bucketName, dirPath, exclusionFilter) +} + // ListChildrenFiles recursively lists all children files. func (g *GCSClient) ListChildrenFiles(ctx context.Context, bucketName, dirPath string) ([]string, error) { - return g.list(ctx, bucketName, strings.TrimRight(dirPath, " /")+"/", "") + return g.listChildren(ctx, bucketName, dirPath, "") } // ListDirectChildren lists direct children paths (including files and directories). @@ -156,7 +164,7 @@ func (g *GCSClient) ListDirectChildren(ctx context.Context, bucketName, dirPath // If there are 2 directories named "foo" and "foobar", // then given storagePath "foo" will get files both under "foo" and "foobar". // Add trailling slash to storagePath, so that only gets children under given directory. - return g.list(ctx, bucketName, strings.TrimRight(dirPath, " /")+"/", "/") + return g.listChildren(ctx, bucketName, dirPath, "/") } // CopyObject copies objects from one location to another. Assumes both source and destination buckets exist. diff --git a/vendor/knative.dev/pkg/test/spoof/spoof.go b/vendor/knative.dev/pkg/test/spoof/spoof.go index 9ac2073183..c3a0f7b877 100644 --- a/vendor/knative.dev/pkg/test/spoof/spoof.go +++ b/vendor/knative.dev/pkg/test/spoof/spoof.go @@ -34,9 +34,9 @@ import ( "knative.dev/pkg/test/ingress" "knative.dev/pkg/test/logging" "knative.dev/pkg/test/zipkin" + "knative.dev/pkg/tracing/propagation/tracecontextb3" "go.opencensus.io/plugin/ochttp" - "go.opencensus.io/plugin/ochttp/propagation/b3" "go.opencensus.io/trace" ) @@ -135,7 +135,7 @@ func New( // Enable Zipkin tracing roundTripper := &ochttp.Transport{ Base: transport, - Propagation: &b3.HTTPFormat{}, + Propagation: tracecontextb3.TraceContextEgress, } sc := SpoofingClient{ diff --git a/vendor/knative.dev/pkg/testutils/clustermanager/perf-tests/main.go b/vendor/knative.dev/pkg/testutils/clustermanager/perf-tests/main.go index 70b0e88ba2..f8084c0780 100644 --- a/vendor/knative.dev/pkg/testutils/clustermanager/perf-tests/main.go +++ b/vendor/knative.dev/pkg/testutils/clustermanager/perf-tests/main.go @@ -27,6 +27,7 @@ import ( var ( isRecreate bool isReconcile bool + isDelete bool gcpProjectName string repoName string benchmarkRootFolder string @@ -40,10 +41,11 @@ func main() { flag.StringVar(&benchmarkRootFolder, "benchmark-root", "", "root folder of the benchmarks") flag.BoolVar(&isRecreate, "recreate", false, "is recreate operation or not") flag.BoolVar(&isReconcile, "reconcile", false, "is reconcile operation or not") + flag.BoolVar(&isDelete, "delete", false, "is delete operation or not") flag.Parse() - if isRecreate && isReconcile { - log.Fatal("Only one operation can be specified, either recreate or reconcile") + if (isRecreate && isReconcile) || (isRecreate && isDelete) || (isReconcile && isDelete) { + log.Fatal("--recreate, --reconcile and --delete are mutually exclusive") } client, err := testPkg.NewClient(gkeEnvironment) @@ -61,7 +63,12 @@ func main() { log.Fatalf("Failed reconciling clusters for repo %q: %v", repoName, err) } log.Printf("Done with reconciling clusters for repo %q", repoName) + case isDelete: + if err := client.DeleteClusters(gcpProjectName, repoName, benchmarkRootFolder); err != nil { + log.Fatalf("Failed deleting clusters for repo %q: %v", repoName, err) + } + log.Printf("Done with deleting clusters for repo %q", repoName) default: - log.Fatal("One operation must be specified, either recreate or reconcile") + log.Fatal("One operation must be specified, either recreate, reconcile or delete") } } diff --git a/vendor/knative.dev/pkg/testutils/clustermanager/perf-tests/pkg/cluster.go b/vendor/knative.dev/pkg/testutils/clustermanager/perf-tests/pkg/cluster.go index a388c5d758..90f0ccfc57 100644 --- a/vendor/knative.dev/pkg/testutils/clustermanager/perf-tests/pkg/cluster.go +++ b/vendor/knative.dev/pkg/testutils/clustermanager/perf-tests/pkg/cluster.go @@ -103,6 +103,19 @@ func (gc *gkeClient) ReconcileClusters(gcpProject, repo, benchmarkRoot string) e return gc.processClusters(gcpProject, repo, benchmarkRoot, handleExistingCluster, handleNewClusterConfig) } +// DeleteClusters will delete all existing clusters. +func (gc *gkeClient) DeleteClusters(gcpProject, repo, benchmarkRoot string) error { + handleExistingCluster := func(cluster container.Cluster, configExists bool, config ClusterConfig) error { + // retain the cluster, if the cluster config is unchanged + return gc.deleteClusterWithRetries(gcpProject, cluster) + } + handleNewClusterConfig := func(clusterName string, clusterConfig ClusterConfig) error { + // do nothing + return nil + } + return gc.processClusters(gcpProject, repo, benchmarkRoot, handleExistingCluster, handleNewClusterConfig) +} + // processClusters will process existing clusters and configs for new clusters, // with the corresponding functions provided by callers. func (gc *gkeClient) processClusters( diff --git a/vendor/knative.dev/pkg/tracing/http.go b/vendor/knative.dev/pkg/tracing/http.go index 2a5d65c521..89509ed0b0 100644 --- a/vendor/knative.dev/pkg/tracing/http.go +++ b/vendor/knative.dev/pkg/tracing/http.go @@ -22,6 +22,7 @@ import ( "go.opencensus.io/plugin/ochttp" "go.opencensus.io/trace" "k8s.io/apimachinery/pkg/util/sets" + "knative.dev/pkg/tracing/propagation/tracecontextb3" ) var ( @@ -50,6 +51,7 @@ func HTTPSpanIgnoringPaths(pathsToIgnore ...string) func(http.Handler) http.Hand } return underlyingSampling }, + Propagation: tracecontextb3.TraceContextEgress, } } } diff --git a/vendor/knative.dev/pkg/tracing/propagation/http_format_sequence.go b/vendor/knative.dev/pkg/tracing/propagation/http_format_sequence.go new file mode 100644 index 0000000000..9a11cbfe9e --- /dev/null +++ b/vendor/knative.dev/pkg/tracing/propagation/http_format_sequence.go @@ -0,0 +1,53 @@ +/* +Copyright 2020 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 propagation + +import ( + "net/http" + + "go.opencensus.io/trace" + "go.opencensus.io/trace/propagation" +) + +// HTTPFormatSequence is a propagation.HTTPFormat that applies multiple other propagation formats. +// For incoming requests, it will use the first SpanContext it can find, checked in the order of +// HTTPFormatSequence.Ingress. +// For outgoing requests, it will apply all the formats to the outgoing request, in the order of +// HTTPFormatSequence.Egress. +type HTTPFormatSequence struct { + Ingress []propagation.HTTPFormat + Egress []propagation.HTTPFormat +} + +var _ propagation.HTTPFormat = (*HTTPFormatSequence)(nil) + +// SpanContextFromRequest satisfies the propagation.HTTPFormat interface. +func (h *HTTPFormatSequence) SpanContextFromRequest(req *http.Request) (trace.SpanContext, bool) { + for _, format := range h.Ingress { + if sc, ok := format.SpanContextFromRequest(req); ok { + return sc, true + } + } + return trace.SpanContext{}, false +} + +// SpanContextToRequest satisfies the propagation.HTTPFormat interface. +func (h *HTTPFormatSequence) SpanContextToRequest(sc trace.SpanContext, req *http.Request) { + for _, format := range h.Egress { + format.SpanContextToRequest(sc, req) + } +} diff --git a/vendor/knative.dev/pkg/tracing/propagation/tracecontextb3/http_format.go b/vendor/knative.dev/pkg/tracing/propagation/tracecontextb3/http_format.go new file mode 100644 index 0000000000..0853ff06c6 --- /dev/null +++ b/vendor/knative.dev/pkg/tracing/propagation/tracecontextb3/http_format.go @@ -0,0 +1,61 @@ +/* +Copyright 2020 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 tracecontextb3 + +import ( + "go.opencensus.io/plugin/ochttp/propagation/b3" + "go.opencensus.io/plugin/ochttp/propagation/tracecontext" + ocpropagation "go.opencensus.io/trace/propagation" + "knative.dev/pkg/tracing/propagation" +) + +// TraceContextB3Egress is a propagation.HTTPFormat that reads both TraceContext and B3 tracing +// formats, preferring TraceContext. It always writes both formats. +var TraceContextB3Egress = &propagation.HTTPFormatSequence{ + Ingress: []ocpropagation.HTTPFormat{ + &tracecontext.HTTPFormat{}, + &b3.HTTPFormat{}, + }, + Egress: []ocpropagation.HTTPFormat{ + &tracecontext.HTTPFormat{}, + &b3.HTTPFormat{}, + }, +} + +// TraceContextEgress is a propagation.HTTPFormat that reads both TraceContext and B3 tracing +// formats, preferring TraceContext. It always writes TraceContext format exclusively. +var TraceContextEgress = &propagation.HTTPFormatSequence{ + Ingress: []ocpropagation.HTTPFormat{ + &tracecontext.HTTPFormat{}, + &b3.HTTPFormat{}, + }, + Egress: []ocpropagation.HTTPFormat{ + &tracecontext.HTTPFormat{}, + }, +} + +// B3Egress is a propagation.HTTPFormat that reads both TraceContext and B3 tracing formats, +// preferring TraceContext. It always writes B3 format exclusively. +var B3Egress = &propagation.HTTPFormatSequence{ + Ingress: []ocpropagation.HTTPFormat{ + &tracecontext.HTTPFormat{}, + &b3.HTTPFormat{}, + }, + Egress: []ocpropagation.HTTPFormat{ + &b3.HTTPFormat{}, + }, +} diff --git a/vendor/knative.dev/pkg/webhook/conversion.go b/vendor/knative.dev/pkg/webhook/conversion.go index 146ac259f9..73cddd7a4b 100644 --- a/vendor/knative.dev/pkg/webhook/conversion.go +++ b/vendor/knative.dev/pkg/webhook/conversion.go @@ -54,6 +54,10 @@ func conversionHandler(rootLogger *zap.SugaredLogger, stats StatsReporter, c Con ctx := logging.WithLogger(r.Context(), logger) response := apixv1.ConversionReview{ + // Use the same type meta as the request - this is required by the K8s API + // note: v1beta1 & v1 ConversionReview shapes are identical so even though + // we're using v1 types we still support v1beta1 conversion requests + TypeMeta: review.TypeMeta, Response: c.Convert(ctx, review.Request), } diff --git a/vendor/knative.dev/serving/pkg/apis/autoscaling/annotation_validation.go b/vendor/knative.dev/serving/pkg/apis/autoscaling/annotation_validation.go index 3551284b9a..0359f48caf 100644 --- a/vendor/knative.dev/serving/pkg/apis/autoscaling/annotation_validation.go +++ b/vendor/knative.dev/serving/pkg/apis/autoscaling/annotation_validation.go @@ -162,7 +162,7 @@ func validateMetric(annotations map[string]string) *apis.FieldError { } case HPA: switch metric { - case CPU, Concurrency, RPS: + case CPU: return nil } default: diff --git a/vendor/modules.txt b/vendor/modules.txt index 662f943f69..d90aa8a000 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -97,7 +97,7 @@ github.com/census-instrumentation/opencensus-proto/gen-go/resource/v1 github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1 # github.com/cespare/xxhash/v2 v2.1.1 github.com/cespare/xxhash/v2 -# github.com/cloudevents/sdk-go v1.2.0 +# github.com/cloudevents/sdk-go v1.0.0 ## explicit github.com/cloudevents/sdk-go github.com/cloudevents/sdk-go/pkg/cloudevents @@ -107,7 +107,6 @@ github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec/json github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec/text github.com/cloudevents/sdk-go/pkg/cloudevents/datacodec/xml -github.com/cloudevents/sdk-go/pkg/cloudevents/extensions github.com/cloudevents/sdk-go/pkg/cloudevents/observability github.com/cloudevents/sdk-go/pkg/cloudevents/transport github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http @@ -609,7 +608,7 @@ google.golang.org/protobuf/types/pluginpb gopkg.in/inf.v0 # gopkg.in/yaml.v2 v2.3.0 => gopkg.in/yaml.v2 v2.2.2 gopkg.in/yaml.v2 -# gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22 +# gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d gopkg.in/yaml.v3 # honnef.co/go/tools v0.0.1-2020.1.4 => honnef.co/go/tools v0.0.1-2019.2.3 honnef.co/go/tools/arg @@ -1024,15 +1023,17 @@ k8s.io/utils/buffer k8s.io/utils/integer k8s.io/utils/pointer k8s.io/utils/trace -# knative.dev/eventing v0.15.1-0.20200619221325-e8ca69f837c7 +# knative.dev/eventing v0.15.1-0.20200623172931-13e513727e77 ## explicit knative.dev/eventing/pkg/apis/config knative.dev/eventing/pkg/apis/configs knative.dev/eventing/pkg/apis/configs/v1alpha1 knative.dev/eventing/pkg/apis/duck +knative.dev/eventing/pkg/apis/duck/v1 knative.dev/eventing/pkg/apis/duck/v1alpha1 knative.dev/eventing/pkg/apis/duck/v1beta1 knative.dev/eventing/pkg/apis/eventing +knative.dev/eventing/pkg/apis/eventing/v1 knative.dev/eventing/pkg/apis/eventing/v1beta1 knative.dev/eventing/pkg/apis/flows knative.dev/eventing/pkg/apis/flows/v1beta1 @@ -1047,6 +1048,8 @@ knative.dev/eventing/pkg/client/clientset/versioned/fake knative.dev/eventing/pkg/client/clientset/versioned/scheme knative.dev/eventing/pkg/client/clientset/versioned/typed/configs/v1alpha1 knative.dev/eventing/pkg/client/clientset/versioned/typed/configs/v1alpha1/fake +knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1 +knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1/fake knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1beta1 knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1beta1/fake knative.dev/eventing/pkg/client/clientset/versioned/typed/flows/v1beta1 @@ -1061,6 +1064,7 @@ knative.dev/eventing/pkg/client/informers/externalversions knative.dev/eventing/pkg/client/informers/externalversions/configs knative.dev/eventing/pkg/client/informers/externalversions/configs/v1alpha1 knative.dev/eventing/pkg/client/informers/externalversions/eventing +knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1 knative.dev/eventing/pkg/client/informers/externalversions/eventing/v1beta1 knative.dev/eventing/pkg/client/informers/externalversions/flows knative.dev/eventing/pkg/client/informers/externalversions/flows/v1beta1 @@ -1076,6 +1080,7 @@ knative.dev/eventing/pkg/client/injection/informers/eventing/v1beta1/broker knative.dev/eventing/pkg/client/injection/informers/factory knative.dev/eventing/pkg/client/injection/reconciler/eventing/v1beta1/broker knative.dev/eventing/pkg/client/listers/configs/v1alpha1 +knative.dev/eventing/pkg/client/listers/eventing/v1 knative.dev/eventing/pkg/client/listers/eventing/v1beta1 knative.dev/eventing/pkg/client/listers/flows/v1beta1 knative.dev/eventing/pkg/client/listers/messaging/v1beta1 @@ -1110,11 +1115,11 @@ knative.dev/eventing/test/test_images/event-sender knative.dev/eventing/test/test_images/performance knative.dev/eventing/test/test_images/recordevents knative.dev/eventing/test/test_images/transformevents -# knative.dev/networking v0.0.0-20200619041525-1faac2ec5d38 +# knative.dev/networking v0.0.0-20200622163826-421cd312c651 knative.dev/networking/pkg/apis/config knative.dev/networking/pkg/apis/networking knative.dev/networking/pkg/apis/networking/v1alpha1 -# knative.dev/pkg v0.0.0-20200622015826-5e60b6f8633c +# knative.dev/pkg v0.0.0-20200623173527-5658d93fb07e ## explicit knative.dev/pkg/apis knative.dev/pkg/apis/duck @@ -1209,6 +1214,8 @@ knative.dev/pkg/testutils/clustermanager/perf-tests/pkg knative.dev/pkg/third_party/mako/proto/quickstore_go_proto knative.dev/pkg/tracing knative.dev/pkg/tracing/config +knative.dev/pkg/tracing/propagation +knative.dev/pkg/tracing/propagation/tracecontextb3 knative.dev/pkg/tracker knative.dev/pkg/version knative.dev/pkg/webhook @@ -1219,7 +1226,7 @@ knative.dev/pkg/webhook/resourcesemantics knative.dev/pkg/webhook/resourcesemantics/conversion knative.dev/pkg/webhook/resourcesemantics/defaulting knative.dev/pkg/webhook/resourcesemantics/validation -# knative.dev/serving v0.15.1-0.20200621202726-40edbdd01f1c +# knative.dev/serving v0.15.1-0.20200623164334-a956ab8df9fa ## explicit knative.dev/serving/pkg/apis/autoscaling knative.dev/serving/pkg/apis/autoscaling/v1alpha1 @@ -1258,7 +1265,8 @@ knative.dev/serving/pkg/client/listers/autoscaling/v1alpha1 knative.dev/serving/pkg/client/listers/serving/v1 knative.dev/serving/pkg/client/listers/serving/v1alpha1 knative.dev/serving/pkg/client/listers/serving/v1beta1 -# knative.dev/test-infra v0.0.0-20200619200026-0b0587234302 +# knative.dev/test-infra v0.0.0-20200623145727-e9ff5263be06 +## explicit knative.dev/test-infra/scripts # sigs.k8s.io/yaml v1.2.0 => sigs.k8s.io/yaml v1.1.0 ## explicit From f047a3c8a5118f6ac4ae19986f40c6293f869ec0 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Tue, 23 Jun 2020 16:46:57 -0700 Subject: [PATCH 19/28] implementing krshaped --- pkg/apis/broker/v1beta1/broker_types.go | 14 +++++++++++ pkg/apis/broker/v1beta1/broker_types_test.go | 18 ++++++++++++++ pkg/apis/broker/v1beta1/trigger_types.go | 14 +++++++++++ pkg/apis/broker/v1beta1/trigger_types_test.go | 18 ++++++++++++++ .../v1beta1/cloudauditlogssource_types.go | 12 ++++++++++ .../cloudauditlogssource_types_test.go | 17 +++++++++++++ .../events/v1beta1/cloudbuildsource_types.go | 11 +++++++++ .../v1beta1/cloudbuildsource_types_test.go | 17 +++++++++++++ .../events/v1beta1/cloudpubsubsource_types.go | 12 ++++++++++ .../v1beta1/cloudpubsubsource_types_test.go | 17 +++++++++++++ .../v1beta1/cloudschedulersource_types.go | 12 ++++++++++ .../cloudschedulersource_types_test.go | 17 +++++++++++++ .../v1beta1/cloudstoragesource_types.go | 13 ++++++++++ .../v1beta1/cloudstoragesource_types_test.go | 17 +++++++++++++ .../v1beta1/pullsubscription_types.go | 24 +++++++++++++++---- .../v1beta1/pullsubscription_types_test.go | 17 +++++++++++++ pkg/apis/intevents/v1beta1/topic_types.go | 23 ++++++++++++++---- .../intevents/v1beta1/topic_types_test.go | 17 +++++++++++++ pkg/apis/messaging/v1beta1/channel_types.go | 11 +++++++++ .../messaging/v1beta1/channel_types_test.go | 17 +++++++++++++ test/test_images/receiver/main.go | 14 +++++------ 21 files changed, 314 insertions(+), 18 deletions(-) diff --git a/pkg/apis/broker/v1beta1/broker_types.go b/pkg/apis/broker/v1beta1/broker_types.go index dddd867e2f..cda538dc60 100644 --- a/pkg/apis/broker/v1beta1/broker_types.go +++ b/pkg/apis/broker/v1beta1/broker_types.go @@ -22,6 +22,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" eventingv1beta1 "knative.dev/eventing/pkg/apis/eventing/v1beta1" "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/pkg/kmeta" ) @@ -66,6 +67,9 @@ var ( // Check that we can create OwnerReferences to a Broker. _ kmeta.OwnerRefable = (*Broker)(nil) + + // Check that we implement KRShaped. + _ duckv1.KRShaped = (*Broker)(nil) ) // BrokerStatus represents the current state of a Broker. @@ -112,3 +116,13 @@ func (b *Broker) GetGroupVersionKind() schema.GroupVersionKind { func (b *Broker) GetUntypedSpec() interface{} { return b.Spec } + +// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface. +func (*Broker) GetConditionSet() apis.ConditionSet { + return brokerCondSet +} + +// GetStatus retrieves the status of the Broker. Implements the KRShaped interface. +func (b *Broker) GetStatus() *duckv1.Status { + return &b.Status.Status +} diff --git a/pkg/apis/broker/v1beta1/broker_types_test.go b/pkg/apis/broker/v1beta1/broker_types_test.go index 9a9f34a3e6..11752bcfb1 100644 --- a/pkg/apis/broker/v1beta1/broker_types_test.go +++ b/pkg/apis/broker/v1beta1/broker_types_test.go @@ -22,6 +22,7 @@ import ( "github.com/google/go-cmp/cmp" "k8s.io/apimachinery/pkg/runtime/schema" eventingv1beta1 "knative.dev/eventing/pkg/apis/eventing/v1beta1" + "knative.dev/pkg/apis" ) func TestBroker_GetGroupVersionKind(t *testing.T) { @@ -46,3 +47,20 @@ func TestBroker_GetUntypedSpec(t *testing.T) { t.Errorf("untyped spec was not a BrokerSpec") } } + +func TestBroker_GetConditionSet(t *testing.T) { + b := &Broker{} + + if got, want := b.GetConditionSet().GetTopLevelConditionType(), apis.ConditionReady; got != want { + t.Errorf("GetTopLevelCondition=%v, want=%v", got, want) + } +} + +func TestBroker_GetStatus(t *testing.T) { + b := &Broker{ + Status: BrokerStatus{}, + } + if got, want := b.GetStatus(), &b.Status.Status; got != want { + t.Errorf("GetStatus=%v, want=%v", got, want) + } +} diff --git a/pkg/apis/broker/v1beta1/trigger_types.go b/pkg/apis/broker/v1beta1/trigger_types.go index 50f03f26d6..5ff048a0f9 100644 --- a/pkg/apis/broker/v1beta1/trigger_types.go +++ b/pkg/apis/broker/v1beta1/trigger_types.go @@ -22,6 +22,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" eventingv1beta1 "knative.dev/eventing/pkg/apis/eventing/v1beta1" "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/pkg/kmeta" ) @@ -66,6 +67,9 @@ var ( // Check that we can create OwnerReferences to a Trigger. _ kmeta.OwnerRefable = (*Trigger)(nil) + + // Check that we implement KRShaped. + _ duckv1.KRShaped = (*Trigger)(nil) ) // TriggerStatus represents the current state of a Trigger. @@ -109,3 +113,13 @@ func (t *Trigger) GetGroupVersionKind() schema.GroupVersionKind { func (t *Trigger) GetUntypedSpec() interface{} { return t.Spec } + +// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface. +func (*Trigger) GetConditionSet() apis.ConditionSet { + return triggerCondSet +} + +// GetStatus retrieves the status of the Trigger. Implements the KRShaped interface. +func (t *Trigger) GetStatus() *duckv1.Status { + return &t.Status.Status +} diff --git a/pkg/apis/broker/v1beta1/trigger_types_test.go b/pkg/apis/broker/v1beta1/trigger_types_test.go index a3f316e931..f5fb303975 100644 --- a/pkg/apis/broker/v1beta1/trigger_types_test.go +++ b/pkg/apis/broker/v1beta1/trigger_types_test.go @@ -22,6 +22,7 @@ import ( "github.com/google/go-cmp/cmp" "k8s.io/apimachinery/pkg/runtime/schema" eventingv1beta1 "knative.dev/eventing/pkg/apis/eventing/v1beta1" + "knative.dev/pkg/apis" ) func TestTrigger_GetGroupVersionKind(t *testing.T) { @@ -46,3 +47,20 @@ func TestTrigger_GetUntypedSpec(t *testing.T) { t.Errorf("untyped spec was not a TriggerSpec") } } + +func TestTrigger_GetConditionSet(t *testing.T) { + tr := &Trigger{} + + if got, want := tr.GetConditionSet().GetTopLevelConditionType(), apis.ConditionReady; got != want { + t.Errorf("GetTopLevelCondition=%v, want=%v", got, want) + } +} + +func TestTrigger_GetStatus(t *testing.T) { + tr := &Trigger{ + Status: TriggerStatus{}, + } + if got, want := tr.GetStatus(), &tr.Status.Status; got != want { + t.Errorf("GetStatus=%v, want=%v", got, want) + } +} diff --git a/pkg/apis/events/v1beta1/cloudauditlogssource_types.go b/pkg/apis/events/v1beta1/cloudauditlogssource_types.go index adbd9646d5..ff0787cb9e 100644 --- a/pkg/apis/events/v1beta1/cloudauditlogssource_types.go +++ b/pkg/apis/events/v1beta1/cloudauditlogssource_types.go @@ -26,6 +26,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/pkg/kmeta" "knative.dev/pkg/webhook/resourcesemantics" ) @@ -53,6 +54,7 @@ var ( _ resourcesemantics.GenericCRD = (*CloudAuditLogsSource)(nil) _ kngcpduck.Identifiable = (*CloudAuditLogsSource)(nil) _ kngcpduck.PubSubable = (*CloudAuditLogsSource)(nil) + _ duckv1.KRShaped = (*CloudAuditLogsSource)(nil) ) const ( @@ -144,3 +146,13 @@ type CloudAuditLogsSourceList struct { Items []CloudAuditLogsSource `json:"items"` } + +// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface. +func (*CloudAuditLogsSource) GetConditionSet() apis.ConditionSet { + return auditLogsSourceCondSet +} + +// GetStatus retrieves the status of the CloudAuditLogsSource. Implements the KRShaped interface. +func (s *CloudAuditLogsSource) GetStatus() *duckv1.Status { + return &s.Status.Status +} diff --git a/pkg/apis/events/v1beta1/cloudauditlogssource_types_test.go b/pkg/apis/events/v1beta1/cloudauditlogssource_types_test.go index 7ee88f194a..6f5f128b82 100644 --- a/pkg/apis/events/v1beta1/cloudauditlogssource_types_test.go +++ b/pkg/apis/events/v1beta1/cloudauditlogssource_types_test.go @@ -117,3 +117,20 @@ func TestCloudAuditLogsSourceIdentityStatus(t *testing.T) { t.Errorf("failed to get expected (-want, +got) = %v", diff) } } + +func TestCloudAuditLogsSource_GetConditionSet(t *testing.T) { + s := &CloudAuditLogsSource{} + + if got, want := s.GetConditionSet().GetTopLevelConditionType(), apis.ConditionReady; got != want { + t.Errorf("GetTopLevelCondition=%v, want=%v", got, want) + } +} + +func TestCloudAuditLogsSource_GetStatus(t *testing.T) { + s := &CloudAuditLogsSource{ + Status: CloudAuditLogsSourceStatus{}, + } + if got, want := s.GetStatus(), &s.Status.Status; got != want { + t.Errorf("GetStatus=%v, want=%v", got, want) + } +} diff --git a/pkg/apis/events/v1beta1/cloudbuildsource_types.go b/pkg/apis/events/v1beta1/cloudbuildsource_types.go index 72a52dbe33..bccba048c4 100644 --- a/pkg/apis/events/v1beta1/cloudbuildsource_types.go +++ b/pkg/apis/events/v1beta1/cloudbuildsource_types.go @@ -46,6 +46,7 @@ var ( _ kngcpduck.PubSubable = (*CloudBuildSource)(nil) _ kngcpduck.Identifiable = (*CloudBuildSource)(nil) _ = duck.VerifyType(&CloudBuildSource{}, &duckv1.Conditions{}) + _ duckv1.KRShaped = (*CloudBuildSource)(nil) ) // CloudBuildSourceSpec defines the desired state of the CloudBuildSource. @@ -123,3 +124,13 @@ func (bs *CloudBuildSource) PubSubStatus() *duckv1beta1.PubSubStatus { func (bs *CloudBuildSource) ConditionSet() *apis.ConditionSet { return &buildCondSet } + +// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface. +func (*CloudBuildSource) GetConditionSet() apis.ConditionSet { + return buildCondSet +} + +// GetStatus retrieves the status of the CloudBuildSource. Implements the KRShaped interface. +func (s *CloudBuildSource) GetStatus() *duckv1.Status { + return &s.Status.Status +} diff --git a/pkg/apis/events/v1beta1/cloudbuildsource_types_test.go b/pkg/apis/events/v1beta1/cloudbuildsource_types_test.go index 170d0f7385..57a3853b29 100644 --- a/pkg/apis/events/v1beta1/cloudbuildsource_types_test.go +++ b/pkg/apis/events/v1beta1/cloudbuildsource_types_test.go @@ -100,3 +100,20 @@ func TestCloudBuildSourceConditionSet(t *testing.T) { t.Errorf("failed to get expected (-want, +got) = %v", diff) } } + +func TestCloudBuildSource_GetConditionSet(t *testing.T) { + s := &CloudBuildSource{} + + if got, want := s.GetConditionSet().GetTopLevelConditionType(), apis.ConditionReady; got != want { + t.Errorf("GetTopLevelCondition=%v, want=%v", got, want) + } +} + +func TestCloudBuildSource_GetStatus(t *testing.T) { + s := &CloudBuildSource{ + Status: CloudBuildSourceStatus{}, + } + if got, want := s.GetStatus(), &s.Status.Status; got != want { + t.Errorf("GetStatus=%v, want=%v", got, want) + } +} diff --git a/pkg/apis/events/v1beta1/cloudpubsubsource_types.go b/pkg/apis/events/v1beta1/cloudpubsubsource_types.go index 432190162c..0573f720d8 100644 --- a/pkg/apis/events/v1beta1/cloudpubsubsource_types.go +++ b/pkg/apis/events/v1beta1/cloudpubsubsource_types.go @@ -26,6 +26,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/pkg/kmeta" "knative.dev/pkg/webhook/resourcesemantics" ) @@ -54,6 +55,7 @@ var ( _ resourcesemantics.GenericCRD = (*CloudPubSubSource)(nil) _ kngcpduck.Identifiable = (*CloudPubSubSource)(nil) _ kngcpduck.PubSubable = (*CloudPubSubSource)(nil) + _ duckv1.KRShaped = (*CloudPubSubSource)(nil) ) // CloudPubSubSourceSpec defines the desired state of the CloudPubSubSource. @@ -174,3 +176,13 @@ func (ps *CloudPubSubSource) PubSubSpec() *duckv1beta1.PubSubSpec { func (s *CloudPubSubSource) PubSubStatus() *duckv1beta1.PubSubStatus { return &s.Status.PubSubStatus } + +// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface. +func (*CloudPubSubSource) GetConditionSet() apis.ConditionSet { + return pubSubCondSet +} + +// GetStatus retrieves the status of the CloudPubSubSource. Implements the KRShaped interface. +func (s *CloudPubSubSource) GetStatus() *duckv1.Status { + return &s.Status.Status +} diff --git a/pkg/apis/events/v1beta1/cloudpubsubsource_types_test.go b/pkg/apis/events/v1beta1/cloudpubsubsource_types_test.go index 3be55e3ab6..d2b87caf7d 100644 --- a/pkg/apis/events/v1beta1/cloudpubsubsource_types_test.go +++ b/pkg/apis/events/v1beta1/cloudpubsubsource_types_test.go @@ -146,3 +146,20 @@ func TestCloudPubSubSourceConditionSet(t *testing.T) { t.Errorf("failed to get expected (-want, +got) = %v", diff) } } + +func TestCloudPubSubSource_GetConditionSet(t *testing.T) { + s := &CloudPubSubSource{} + + if got, want := s.GetConditionSet().GetTopLevelConditionType(), apis.ConditionReady; got != want { + t.Errorf("GetTopLevelCondition=%v, want=%v", got, want) + } +} + +func TestCloudPubSubSource_GetStatus(t *testing.T) { + s := &CloudPubSubSource{ + Status: CloudPubSubSourceStatus{}, + } + if got, want := s.GetStatus(), &s.Status.Status; got != want { + t.Errorf("GetStatus=%v, want=%v", got, want) + } +} \ No newline at end of file diff --git a/pkg/apis/events/v1beta1/cloudschedulersource_types.go b/pkg/apis/events/v1beta1/cloudschedulersource_types.go index db192a5b7e..d30b449317 100644 --- a/pkg/apis/events/v1beta1/cloudschedulersource_types.go +++ b/pkg/apis/events/v1beta1/cloudschedulersource_types.go @@ -25,6 +25,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/pkg/kmeta" "knative.dev/pkg/webhook/resourcesemantics" ) @@ -52,6 +53,7 @@ var ( _ resourcesemantics.GenericCRD = (*CloudSchedulerSource)(nil) _ kngcpduck.Identifiable = (*CloudSchedulerSource)(nil) _ kngcpduck.PubSubable = (*CloudSchedulerSource)(nil) + _ duckv1.KRShaped = (*CloudSchedulerSource)(nil) ) const ( @@ -148,3 +150,13 @@ type CloudSchedulerSourceList struct { Items []CloudSchedulerSource `json:"items"` } + +// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface. +func (*CloudSchedulerSource) GetConditionSet() apis.ConditionSet { + return schedulerCondSet +} + +// GetStatus retrieves the status of the CloudSchedulerSource. Implements the KRShaped interface. +func (s *CloudSchedulerSource) GetStatus() *duckv1.Status { + return &s.Status.Status +} diff --git a/pkg/apis/events/v1beta1/cloudschedulersource_types_test.go b/pkg/apis/events/v1beta1/cloudschedulersource_types_test.go index e224ad63e0..c333a2adc7 100644 --- a/pkg/apis/events/v1beta1/cloudschedulersource_types_test.go +++ b/pkg/apis/events/v1beta1/cloudschedulersource_types_test.go @@ -107,3 +107,20 @@ func TestCloudSchedulerSourceIdentityStatus(t *testing.T) { t.Errorf("failed to get expected (-want, +got) = %v", diff) } } + +func TestCloudSchedulerSource_GetConditionSet(t *testing.T) { + s := &CloudSchedulerSource{} + + if got, want := s.GetConditionSet().GetTopLevelConditionType(), apis.ConditionReady; got != want { + t.Errorf("GetTopLevelCondition=%v, want=%v", got, want) + } +} + +func TestCloudSchedulerSource_GetStatus(t *testing.T) { + s := &CloudSchedulerSource{ + Status: CloudSchedulerSourceStatus{}, + } + if got, want := s.GetStatus(), &s.Status.Status; got != want { + t.Errorf("GetStatus=%v, want=%v", got, want) + } +} diff --git a/pkg/apis/events/v1beta1/cloudstoragesource_types.go b/pkg/apis/events/v1beta1/cloudstoragesource_types.go index f68f864a0e..4681a46c47 100644 --- a/pkg/apis/events/v1beta1/cloudstoragesource_types.go +++ b/pkg/apis/events/v1beta1/cloudstoragesource_types.go @@ -27,6 +27,8 @@ import ( "knative.dev/pkg/apis" "knative.dev/pkg/kmeta" "knative.dev/pkg/webhook/resourcesemantics" + + duckv1 "knative.dev/pkg/apis/duck/v1" ) // +genclient @@ -52,6 +54,7 @@ var ( _ resourcesemantics.GenericCRD = (*CloudStorageSource)(nil) _ kngcpduck.Identifiable = (*CloudStorageSource)(nil) _ kngcpduck.PubSubable = (*CloudStorageSource)(nil) + _ duckv1.KRShaped = (*CloudStorageSource)(nil) ) // CloudStorageSourceSpec is the spec for a CloudStorageSource resource @@ -158,3 +161,13 @@ type CloudStorageSourceList struct { Items []CloudStorageSource `json:"items"` } + +// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface. +func (*CloudStorageSource) GetConditionSet() apis.ConditionSet { + return storageCondSet +} + +// GetStatus retrieves the status of the CloudStorageSource. Implements the KRShaped interface. +func (s *CloudStorageSource) GetStatus() *duckv1.Status { + return &s.Status.Status +} diff --git a/pkg/apis/events/v1beta1/cloudstoragesource_types_test.go b/pkg/apis/events/v1beta1/cloudstoragesource_types_test.go index 010c514f99..d4faef1bae 100644 --- a/pkg/apis/events/v1beta1/cloudstoragesource_types_test.go +++ b/pkg/apis/events/v1beta1/cloudstoragesource_types_test.go @@ -105,3 +105,20 @@ func TestCloudStorageSourceIdentityStatus(t *testing.T) { t.Errorf("failed to get expected (-want, +got) = %v", diff) } } + +func TestCloudStorageSource_GetConditionSet(t *testing.T) { + s := &CloudStorageSource{} + + if got, want := s.GetConditionSet().GetTopLevelConditionType(), apis.ConditionReady; got != want { + t.Errorf("GetTopLevelCondition=%v, want=%v", got, want) + } +} + +func TestCloudStorageSource_GetStatus(t *testing.T) { + s := &CloudStorageSource{ + Status: CloudStorageSourceStatus{}, + } + if got, want := s.GetStatus(), &s.Status.Status; got != want { + t.Errorf("GetStatus=%v, want=%v", got, want) + } +} diff --git a/pkg/apis/intevents/v1beta1/pullsubscription_types.go b/pkg/apis/intevents/v1beta1/pullsubscription_types.go index 7acc581217..b7b9e31e9a 100644 --- a/pkg/apis/intevents/v1beta1/pullsubscription_types.go +++ b/pkg/apis/intevents/v1beta1/pullsubscription_types.go @@ -43,11 +43,6 @@ type PullSubscription struct { Status PullSubscriptionStatus `json:"status,omitempty"` } -// PubSubMode returns the mode currently set for PullSubscription. -func (p *PullSubscription) PubSubMode() ModeType { - return p.Spec.Mode -} - // Check that PullSubscription can be converted to other versions. var _ apis.Convertible = (*PullSubscription)(nil) @@ -57,6 +52,10 @@ var _ runtime.Object = (*PullSubscription)(nil) // Check that PullSubscription implements the Conditions duck type. var _ = duck.VerifyType(&PullSubscription{}, &duckv1.Conditions{}) +// Check that PullSubscription implements the KRShaped duck type. +var _ duckv1.KRShaped = (*PullSubscription)(nil) + + // PullSubscriptionSpec defines the desired state of the PullSubscription. type PullSubscriptionSpec struct { v1beta1.PubSubSpec `json:",inline"` @@ -102,6 +101,11 @@ type PullSubscriptionSpec struct { AdapterType string `json:"adapterType,omitempty"` } +// PubSubMode returns the mode currently set for PullSubscription. +func (p *PullSubscription) PubSubMode() ModeType { + return p.Spec.Mode +} + // GetAckDeadline parses AckDeadline and returns the default if an error occurs. func (ps PullSubscriptionSpec) GetAckDeadline() time.Duration { if ps.AckDeadline != nil { @@ -215,3 +219,13 @@ func (s *PullSubscription) IdentityStatus() *v1beta1.IdentityStatus { func (*PullSubscription) ConditionSet() *apis.ConditionSet { return &pullSubscriptionCondSet } + +// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface. +func (*PullSubscription) GetConditionSet() apis.ConditionSet { + return pullSubscriptionCondSet +} + +// GetStatus retrieves the status of the PullSubscription. Implements the KRShaped interface. +func (s *PullSubscription) GetStatus() *duckv1.Status { + return &s.Status.Status +} diff --git a/pkg/apis/intevents/v1beta1/pullsubscription_types_test.go b/pkg/apis/intevents/v1beta1/pullsubscription_types_test.go index ad292b58fd..bc10fdf31e 100644 --- a/pkg/apis/intevents/v1beta1/pullsubscription_types_test.go +++ b/pkg/apis/intevents/v1beta1/pullsubscription_types_test.go @@ -152,3 +152,20 @@ func TestPullSubscriptionConditionSet(t *testing.T) { t.Errorf("failed to get expected (-want, +got) = %v", diff) } } + +func TestPullSubscription_GetConditionSet(t *testing.T) { + s := &PullSubscription{} + + if got, want := s.GetConditionSet().GetTopLevelConditionType(), apis.ConditionReady; got != want { + t.Errorf("GetTopLevelCondition=%v, want=%v", got, want) + } +} + +func TestPullSubscription_GetStatus(t *testing.T) { + s := &PullSubscription{ + Status: PullSubscriptionStatus{}, + } + if got, want := s.GetStatus(), &s.Status.Status; got != want { + t.Errorf("GetStatus=%v, want=%v", got, want) + } +} diff --git a/pkg/apis/intevents/v1beta1/topic_types.go b/pkg/apis/intevents/v1beta1/topic_types.go index b9505ca650..23d9ee868b 100644 --- a/pkg/apis/intevents/v1beta1/topic_types.go +++ b/pkg/apis/intevents/v1beta1/topic_types.go @@ -59,6 +59,9 @@ var _ resourcesemantics.GenericCRD = (*Topic)(nil) // Check that Topic implements the Conditions duck type. var _ = duck.VerifyType(&Topic{}, &duckv1.Conditions{}) +// Check that Topic implements the KRShaped duck type. +var _ duckv1.KRShaped = (*Topic)(nil) + // TopicSpec defines parameters for creating or publishing to a Cloud Pub/Sub // Topic depending on the PropagationPolicy. type TopicSpec struct { @@ -169,16 +172,26 @@ func (t *Topic) GetGroupVersionKind() schema.GroupVersionKind { // Methods for identifiable interface. // IdentitySpec returns the IdentitySpec portion of the Spec. -func (s *Topic) IdentitySpec() *v1beta1.IdentitySpec { - return &s.Spec.IdentitySpec +func (t *Topic) IdentitySpec() *v1beta1.IdentitySpec { + return &t.Spec.IdentitySpec } // IdentityStatus returns the IdentityStatus portion of the Status. -func (s *Topic) IdentityStatus() *v1beta1.IdentityStatus { - return &s.Status.IdentityStatus +func (t *Topic) IdentityStatus() *v1beta1.IdentityStatus { + return &t.Status.IdentityStatus } // ConditionSet returns the apis.ConditionSet of the embedding object -func (ps *Topic) ConditionSet() *apis.ConditionSet { +func (t *Topic) ConditionSet() *apis.ConditionSet { return &topicCondSet } + +// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface. +func (*Topic) GetConditionSet() apis.ConditionSet { + return topicCondSet +} + +// GetStatus retrieves the status of the Topic. Implements the KRShaped interface. +func (t *Topic) GetStatus() *duckv1.Status { + return &t.Status.Status +} diff --git a/pkg/apis/intevents/v1beta1/topic_types_test.go b/pkg/apis/intevents/v1beta1/topic_types_test.go index 65bbddbc9b..da1343d7b5 100644 --- a/pkg/apis/intevents/v1beta1/topic_types_test.go +++ b/pkg/apis/intevents/v1beta1/topic_types_test.go @@ -91,3 +91,20 @@ func TestTopicConditionSet(t *testing.T) { t.Errorf("failed to get expected (-want, +got) = %v", diff) } } + +func TestTopic_GetConditionSet(t *testing.T) { + tp := &Topic{} + + if got, want := tp.GetConditionSet().GetTopLevelConditionType(), apis.ConditionReady; got != want { + t.Errorf("GetTopLevelCondition=%v, want=%v", got, want) + } +} + +func TestTopic_GetStatus(t *testing.T) { + tp := &Topic{ + Status: TopicStatus{}, + } + if got, want := tp.GetStatus(), &tp.Status.Status; got != want { + t.Errorf("GetStatus=%v, want=%v", got, want) + } +} diff --git a/pkg/apis/messaging/v1beta1/channel_types.go b/pkg/apis/messaging/v1beta1/channel_types.go index e0e1eb6de9..5cd8a37377 100644 --- a/pkg/apis/messaging/v1beta1/channel_types.go +++ b/pkg/apis/messaging/v1beta1/channel_types.go @@ -57,6 +57,7 @@ var ( _ runtime.Object = (*Channel)(nil) _ resourcesemantics.GenericCRD = (*Channel)(nil) _ kngcpduck.Identifiable = (*Channel)(nil) + _ duckv1.KRShaped = (*Channel)(nil) ) // ChannelSpec defines which subscribers have expressed interest in @@ -153,3 +154,13 @@ type ChannelList struct { func (c *Channel) GetGroupVersionKind() schema.GroupVersionKind { return SchemeGroupVersion.WithKind("Channel") } + +// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface. +func (*Channel) GetConditionSet() apis.ConditionSet { + return channelCondSet +} + +// GetStatus retrieves the status of the Channel. Implements the KRShaped interface. +func (c *Channel) GetStatus() *duckv1.Status { + return &c.Status.Status +} diff --git a/pkg/apis/messaging/v1beta1/channel_types_test.go b/pkg/apis/messaging/v1beta1/channel_types_test.go index 4339593e13..f7a964a58c 100644 --- a/pkg/apis/messaging/v1beta1/channel_types_test.go +++ b/pkg/apis/messaging/v1beta1/channel_types_test.go @@ -94,3 +94,20 @@ func TestChannelConditionSet(t *testing.T) { t.Errorf("failed to get expected (-want, +got) = %v", diff) } } + +func TestChannel_GetConditionSet(t *testing.T) { + c := &Channel{} + + if got, want := c.GetConditionSet().GetTopLevelConditionType(), apis.ConditionReady; got != want { + t.Errorf("GetTopLevelCondition=%v, want=%v", got, want) + } +} + +func TestChannel_GetStatus(t *testing.T) { + c := &Channel{ + Status: ChannelStatus{}, + } + if got, want := c.GetStatus(), &c.Status.Status; got != want { + t.Errorf("GetStatus=%v, want=%v", got, want) + } +} diff --git a/test/test_images/receiver/main.go b/test/test_images/receiver/main.go index 7228a613d0..fec8715b0d 100644 --- a/test/test_images/receiver/main.go +++ b/test/test_images/receiver/main.go @@ -19,9 +19,7 @@ package main import ( "context" "fmt" - "github.com/google/knative-gcp/pkg/apis/events/v1beta1" "log" - "net/http" cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/knative-gcp/test/e2e/lib" @@ -50,11 +48,11 @@ func (r *Receiver) Receive(event cloudevents.Event) (*cloudevents.Event, error) if event.ID() != lib.E2EDummyEventID { return nil, fmt.Errorf("unexpected cloud event id got=%s, want=%s", event.ID(), lib.E2EDummyEventID) } - event = cloudevents.NewEvent(cloudevents.VersionV1) - event.SetID(lib.E2EDummyRespEventID) - event.SetType(lib.E2EDummyRespEventType) - event.SetSource(lib.E2EDummyRespEventSource) - event.SetData(cloudevents.ApplicationJSON, `{"source": "receiver!"}`) - return + event = cloudevents.NewEvent(cloudevents.VersionV1) + event.SetID(lib.E2EDummyRespEventID) + event.SetType(lib.E2EDummyRespEventType) + event.SetSource(lib.E2EDummyRespEventSource) + event.SetData(cloudevents.ApplicationJSON, `{"source": "receiver!"}`) + return &event, nil } From 9cb134c512ee0189dec0f98e5ae10014b2615436 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Tue, 23 Jun 2020 17:11:48 -0700 Subject: [PATCH 20/28] removing unused genreconciler clients. Doing it so that we do not need to implement KRShaped in all v1alpha1 types --- .../v1alpha1/cloudauditlogssource_types.go | 1 - .../events/v1alpha1/cloudbuildsource_types.go | 1 - .../v1alpha1/cloudpubsubsource_types.go | 1 - .../v1alpha1/cloudschedulersource_types.go | 1 - .../v1alpha1/cloudstoragesource_types.go | 1 - .../intevents/v1alpha1/brokercell_types.go | 13 + .../v1alpha1/brokercell_types_test.go | 18 + .../v1alpha1/pullsubscription_types.go | 1 - pkg/apis/intevents/v1alpha1/topic_types.go | 1 - pkg/apis/messaging/v1alpha1/channel_types.go | 1 - .../cloudauditlogssource/controller.go | 139 ------ .../cloudauditlogssource/reconciler.go | 434 ------------------ .../cloudauditlogssource/stub/controller.go | 54 --- .../cloudauditlogssource/stub/reconciler.go | 87 ---- .../v1alpha1/cloudbuildsource/controller.go | 139 ------ .../v1alpha1/cloudbuildsource/reconciler.go | 434 ------------------ .../cloudbuildsource/stub/controller.go | 54 --- .../cloudbuildsource/stub/reconciler.go | 87 ---- .../v1alpha1/cloudpubsubsource/controller.go | 139 ------ .../v1alpha1/cloudpubsubsource/reconciler.go | 434 ------------------ .../cloudpubsubsource/stub/controller.go | 54 --- .../cloudpubsubsource/stub/reconciler.go | 87 ---- .../cloudschedulersource/controller.go | 139 ------ .../cloudschedulersource/reconciler.go | 434 ------------------ .../cloudschedulersource/stub/controller.go | 54 --- .../cloudschedulersource/stub/reconciler.go | 87 ---- .../v1alpha1/cloudstoragesource/controller.go | 139 ------ .../v1alpha1/cloudstoragesource/reconciler.go | 434 ------------------ .../cloudstoragesource/stub/controller.go | 54 --- .../cloudstoragesource/stub/reconciler.go | 87 ---- .../v1alpha1/pullsubscription/controller.go | 139 ------ .../v1alpha1/pullsubscription/reconciler.go | 434 ------------------ .../pullsubscription/stub/controller.go | 54 --- .../pullsubscription/stub/reconciler.go | 87 ---- .../intevents/v1alpha1/topic/controller.go | 139 ------ .../intevents/v1alpha1/topic/reconciler.go | 434 ------------------ .../v1alpha1/topic/stub/controller.go | 54 --- .../v1alpha1/topic/stub/reconciler.go | 87 ---- .../messaging/v1alpha1/channel/controller.go | 139 ------ .../messaging/v1alpha1/channel/reconciler.go | 434 ------------------ .../v1alpha1/channel/stub/controller.go | 54 --- .../v1alpha1/channel/stub/reconciler.go | 87 ---- pkg/pubsub/adapter/adapter_test.go | 316 +++++++------ 43 files changed, 186 insertions(+), 5881 deletions(-) delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/controller.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/reconciler.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/stub/controller.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/stub/reconciler.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/controller.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/reconciler.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/stub/controller.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/stub/reconciler.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/controller.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/reconciler.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/stub/controller.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/stub/reconciler.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/controller.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/reconciler.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/stub/controller.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/stub/reconciler.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/controller.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/reconciler.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/stub/controller.go delete mode 100644 pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/stub/reconciler.go delete mode 100644 pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/controller.go delete mode 100644 pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/reconciler.go delete mode 100644 pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/stub/controller.go delete mode 100644 pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/stub/reconciler.go delete mode 100644 pkg/client/injection/reconciler/intevents/v1alpha1/topic/controller.go delete mode 100644 pkg/client/injection/reconciler/intevents/v1alpha1/topic/reconciler.go delete mode 100644 pkg/client/injection/reconciler/intevents/v1alpha1/topic/stub/controller.go delete mode 100644 pkg/client/injection/reconciler/intevents/v1alpha1/topic/stub/reconciler.go delete mode 100644 pkg/client/injection/reconciler/messaging/v1alpha1/channel/controller.go delete mode 100644 pkg/client/injection/reconciler/messaging/v1alpha1/channel/reconciler.go delete mode 100644 pkg/client/injection/reconciler/messaging/v1alpha1/channel/stub/controller.go delete mode 100644 pkg/client/injection/reconciler/messaging/v1alpha1/channel/stub/reconciler.go diff --git a/pkg/apis/events/v1alpha1/cloudauditlogssource_types.go b/pkg/apis/events/v1alpha1/cloudauditlogssource_types.go index 94b622ba43..97e3f5c2df 100644 --- a/pkg/apis/events/v1alpha1/cloudauditlogssource_types.go +++ b/pkg/apis/events/v1alpha1/cloudauditlogssource_types.go @@ -32,7 +32,6 @@ import ( ) // +genclient -// +genreconciler // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // CloudAuditLogsSource is a specification for a Cloud Audit Log event source. diff --git a/pkg/apis/events/v1alpha1/cloudbuildsource_types.go b/pkg/apis/events/v1alpha1/cloudbuildsource_types.go index b3a4d91c12..8f9b1adc02 100644 --- a/pkg/apis/events/v1alpha1/cloudbuildsource_types.go +++ b/pkg/apis/events/v1alpha1/cloudbuildsource_types.go @@ -30,7 +30,6 @@ import ( // CloudBuildSource is a specification for a CloudBuildSource resource // +genclient -// +genreconciler // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type CloudBuildSource struct { metav1.TypeMeta `json:",inline"` diff --git a/pkg/apis/events/v1alpha1/cloudpubsubsource_types.go b/pkg/apis/events/v1alpha1/cloudpubsubsource_types.go index f8a7a67c4a..3b50e20a81 100644 --- a/pkg/apis/events/v1alpha1/cloudpubsubsource_types.go +++ b/pkg/apis/events/v1alpha1/cloudpubsubsource_types.go @@ -33,7 +33,6 @@ import ( ) // +genclient -// +genreconciler // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // CloudPubSubSource is a specification for a CloudPubSubSource resource diff --git a/pkg/apis/events/v1alpha1/cloudschedulersource_types.go b/pkg/apis/events/v1alpha1/cloudschedulersource_types.go index dfa7154ec3..c1d4d57177 100644 --- a/pkg/apis/events/v1alpha1/cloudschedulersource_types.go +++ b/pkg/apis/events/v1alpha1/cloudschedulersource_types.go @@ -32,7 +32,6 @@ import ( ) // +genclient -// +genreconciler // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // CloudSchedulerSource is a specification for a CloudSchedulerSource resource diff --git a/pkg/apis/events/v1alpha1/cloudstoragesource_types.go b/pkg/apis/events/v1alpha1/cloudstoragesource_types.go index df63175b57..979f89c5d2 100644 --- a/pkg/apis/events/v1alpha1/cloudstoragesource_types.go +++ b/pkg/apis/events/v1alpha1/cloudstoragesource_types.go @@ -32,7 +32,6 @@ import ( ) // +genclient -// +genreconciler // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // CloudStorageSource is a specification for a Google Cloud CloudStorageSource Source resource diff --git a/pkg/apis/intevents/v1alpha1/brokercell_types.go b/pkg/apis/intevents/v1alpha1/brokercell_types.go index 8c478c4666..72dbe33494 100644 --- a/pkg/apis/intevents/v1alpha1/brokercell_types.go +++ b/pkg/apis/intevents/v1alpha1/brokercell_types.go @@ -63,6 +63,9 @@ var ( // Check that we can create OwnerReferences to a BrokerCell. _ kmeta.OwnerRefable = (*BrokerCell)(nil) + + // Check that BrokerCell implements the KRShaped duck type. + _ duckv1.KRShaped = (*BrokerCell)(nil) ) // BrokerCellSpec defines the desired state of a Brokercell. @@ -103,3 +106,13 @@ func (bc *BrokerCell) GetGroupVersionKind() schema.GroupVersionKind { func (bc *BrokerCell) GetUntypedSpec() interface{} { return bc.Spec } + +// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface. +func (*BrokerCell) GetConditionSet() apis.ConditionSet { + return brokerCellCondSet +} + +// GetStatus retrieves the status of the BrokerCell. Implements the KRShaped interface. +func (bc *BrokerCell) GetStatus() *duckv1.Status { + return &bc.Status.Status +} diff --git a/pkg/apis/intevents/v1alpha1/brokercell_types_test.go b/pkg/apis/intevents/v1alpha1/brokercell_types_test.go index a16525afa1..9c194cd1a2 100644 --- a/pkg/apis/intevents/v1alpha1/brokercell_types_test.go +++ b/pkg/apis/intevents/v1alpha1/brokercell_types_test.go @@ -17,6 +17,7 @@ limitations under the License. package v1alpha1 import ( + "knative.dev/pkg/apis" "testing" "github.com/google/go-cmp/cmp" @@ -45,3 +46,20 @@ func TestBrokerCell_GetUntypedSpec(t *testing.T) { t.Errorf("untyped spec was not a BrokerSpec") } } + +func TestBrokerCell_GetConditionSet(t *testing.T) { + bc := &BrokerCell{} + + if got, want := bc.GetConditionSet().GetTopLevelConditionType(), apis.ConditionReady; got != want { + t.Errorf("GetTopLevelCondition=%v, want=%v", got, want) + } +} + +func TestBrokerCell_GetStatus(t *testing.T) { + bc := &BrokerCell{ + Status: BrokerCellStatus{}, + } + if got, want := bc.GetStatus(), &bc.Status.Status; got != want { + t.Errorf("GetStatus=%v, want=%v", got, want) + } +} diff --git a/pkg/apis/intevents/v1alpha1/pullsubscription_types.go b/pkg/apis/intevents/v1alpha1/pullsubscription_types.go index ef68609010..0a72bf6aed 100644 --- a/pkg/apis/intevents/v1alpha1/pullsubscription_types.go +++ b/pkg/apis/intevents/v1alpha1/pullsubscription_types.go @@ -30,7 +30,6 @@ import ( ) // +genclient -// +genreconciler // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // PullSubscription is the Schema for the gcppullSubscriptions API. diff --git a/pkg/apis/intevents/v1alpha1/topic_types.go b/pkg/apis/intevents/v1alpha1/topic_types.go index 035fe4ebca..030777b5a3 100644 --- a/pkg/apis/intevents/v1alpha1/topic_types.go +++ b/pkg/apis/intevents/v1alpha1/topic_types.go @@ -31,7 +31,6 @@ import ( ) // +genclient -// +genreconciler // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Topic is a resource representing a Topic backed by Google Cloud Pub/Sub. diff --git a/pkg/apis/messaging/v1alpha1/channel_types.go b/pkg/apis/messaging/v1alpha1/channel_types.go index a61899556f..9a2ba945a5 100644 --- a/pkg/apis/messaging/v1alpha1/channel_types.go +++ b/pkg/apis/messaging/v1alpha1/channel_types.go @@ -31,7 +31,6 @@ import ( ) // +genclient -// +genreconciler // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Channel is a resource representing an channel backed by Google Cloud Pub/Sub. diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/controller.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/controller.go deleted file mode 100644 index 1963e2de5c..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/controller.go +++ /dev/null @@ -1,139 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudauditlogssource - -import ( - context "context" - fmt "fmt" - reflect "reflect" - strings "strings" - - versionedscheme "github.com/google/knative-gcp/pkg/client/clientset/versioned/scheme" - client "github.com/google/knative-gcp/pkg/client/injection/client" - cloudauditlogssource "github.com/google/knative-gcp/pkg/client/injection/informers/events/v1alpha1/cloudauditlogssource" - corev1 "k8s.io/api/core/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - scheme "k8s.io/client-go/kubernetes/scheme" - v1 "k8s.io/client-go/kubernetes/typed/core/v1" - record "k8s.io/client-go/tools/record" - kubeclient "knative.dev/pkg/client/injection/kube/client" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -const ( - defaultControllerAgentName = "cloudauditlogssource-controller" - defaultFinalizerName = "cloudauditlogssources.events.cloud.google.com" -) - -// NewImpl returns a controller.Impl that handles queuing and feeding work from -// the queue through an implementation of controller.Reconciler, delegating to -// the provided Interface and optional Finalizer methods. OptionsFn is used to return -// controller.Options to be used but the internal reconciler. -func NewImpl(ctx context.Context, r Interface, optionsFns ...controller.OptionsFn) *controller.Impl { - logger := logging.FromContext(ctx) - - // Check the options function input. It should be 0 or 1. - if len(optionsFns) > 1 { - logger.Fatalf("up to one options function is supported, found %d", len(optionsFns)) - } - - cloudauditlogssourceInformer := cloudauditlogssource.Get(ctx) - - lister := cloudauditlogssourceInformer.Lister() - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client.Get(ctx), - Lister: lister, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - t := reflect.TypeOf(r).Elem() - queueName := fmt.Sprintf("%s.%s", strings.ReplaceAll(t.PkgPath(), "/", "-"), t.Name()) - - impl := controller.NewImpl(rec, logger, queueName) - agentName := defaultControllerAgentName - - // Pass impl to the options. Save any optional results. - for _, fn := range optionsFns { - opts := fn(impl) - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - if opts.AgentName != "" { - agentName = opts.AgentName - } - } - - rec.Recorder = createRecorder(ctx, agentName) - - return impl -} - -func createRecorder(ctx context.Context, agentName string) record.EventRecorder { - logger := logging.FromContext(ctx) - - recorder := controller.GetEventRecorder(ctx) - if recorder == nil { - // Create event broadcaster - logger.Debug("Creating event broadcaster") - eventBroadcaster := record.NewBroadcaster() - watches := []watch.Interface{ - eventBroadcaster.StartLogging(logger.Named("event-broadcaster").Infof), - eventBroadcaster.StartRecordingToSink( - &v1.EventSinkImpl{Interface: kubeclient.Get(ctx).CoreV1().Events("")}), - } - recorder = eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: agentName}) - go func() { - <-ctx.Done() - for _, w := range watches { - w.Stop() - } - }() - } - - return recorder -} - -func init() { - versionedscheme.AddToScheme(scheme.Scheme) -} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/reconciler.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/reconciler.go deleted file mode 100644 index 42baa4ddc3..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/reconciler.go +++ /dev/null @@ -1,434 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudauditlogssource - -import ( - context "context" - json "encoding/json" - fmt "fmt" - reflect "reflect" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" - versioned "github.com/google/knative-gcp/pkg/client/clientset/versioned" - eventsv1alpha1 "github.com/google/knative-gcp/pkg/client/listers/events/v1alpha1" - zap "go.uber.org/zap" - v1 "k8s.io/api/core/v1" - equality "k8s.io/apimachinery/pkg/api/equality" - errors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - sets "k8s.io/apimachinery/pkg/util/sets" - cache "k8s.io/client-go/tools/cache" - record "k8s.io/client-go/tools/record" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -// Interface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.CloudAuditLogsSource. -type Interface interface { - // ReconcileKind implements custom logic to reconcile v1alpha1.CloudAuditLogsSource. Any changes - // to the objects .Status or .Finalizers will be propagated to the stored - // object. It is recommended that implementors do not call any update calls - // for the Kind inside of ReconcileKind, it is the responsibility of the calling - // controller to propagate those properties. The resource passed to ReconcileKind - // will always have an empty deletion timestamp. - ReconcileKind(ctx context.Context, o *v1alpha1.CloudAuditLogsSource) reconciler.Event -} - -// Finalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.CloudAuditLogsSource. -type Finalizer interface { - // FinalizeKind implements custom logic to finalize v1alpha1.CloudAuditLogsSource. Any changes - // to the objects .Status or .Finalizers will be ignored. Returning a nil or - // Normal type reconciler.Event will allow the finalizer to be deleted on - // the resource. The resource passed to FinalizeKind will always have a set - // deletion timestamp. - FinalizeKind(ctx context.Context, o *v1alpha1.CloudAuditLogsSource) reconciler.Event -} - -// ReadOnlyInterface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.CloudAuditLogsSource if they want to process resources for which -// they are not the leader. -type ReadOnlyInterface interface { - // ObserveKind implements logic to observe v1alpha1.CloudAuditLogsSource. - // This method should not write to the API. - ObserveKind(ctx context.Context, o *v1alpha1.CloudAuditLogsSource) reconciler.Event -} - -// ReadOnlyFinalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.CloudAuditLogsSource if they want to process tombstoned resources -// even when they are not the leader. Due to the nature of how finalizers are handled -// there are no guarantees that this will be called. -type ReadOnlyFinalizer interface { - // ObserveFinalizeKind implements custom logic to observe the final state of v1alpha1.CloudAuditLogsSource. - // This method should not write to the API. - ObserveFinalizeKind(ctx context.Context, o *v1alpha1.CloudAuditLogsSource) reconciler.Event -} - -// reconcilerImpl implements controller.Reconciler for v1alpha1.CloudAuditLogsSource resources. -type reconcilerImpl struct { - // LeaderAwareFuncs is inlined to help us implement reconciler.LeaderAware - reconciler.LeaderAwareFuncs - - // Client is used to write back status updates. - Client versioned.Interface - - // Listers index properties about resources - Lister eventsv1alpha1.CloudAuditLogsSourceLister - - // Recorder is an event recorder for recording Event resources to the - // Kubernetes API. - Recorder record.EventRecorder - - // configStore allows for decorating a context with config maps. - // +optional - configStore reconciler.ConfigStore - - // reconciler is the implementation of the business logic of the resource. - reconciler Interface - - // finalizerName is the name of the finalizer to reconcile. - finalizerName string -} - -// Check that our Reconciler implements controller.Reconciler -var _ controller.Reconciler = (*reconcilerImpl)(nil) - -// Check that our generated Reconciler is always LeaderAware. -var _ reconciler.LeaderAware = (*reconcilerImpl)(nil) - -func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versioned.Interface, lister eventsv1alpha1.CloudAuditLogsSourceLister, recorder record.EventRecorder, r Interface, options ...controller.Options) controller.Reconciler { - // Check the options function input. It should be 0 or 1. - if len(options) > 1 { - logger.Fatalf("up to one options struct is supported, found %d", len(options)) - } - - // Fail fast when users inadvertently implement the other LeaderAware interface. - // For the typed reconcilers, Promote shouldn't take any arguments. - if _, ok := r.(reconciler.LeaderAware); ok { - logger.Fatalf("%T implements the incorrect LeaderAware interface. Promote() should not take an argument as genreconciler handles the enqueuing automatically.", r) - } - // TODO: Consider validating when folks implement ReadOnlyFinalizer, but not Finalizer. - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client, - Lister: lister, - Recorder: recorder, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - for _, opts := range options { - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - } - - return rec -} - -// Reconcile implements controller.Reconciler -func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { - logger := logging.FromContext(ctx) - - // Convert the namespace/name string into a distinct namespace and name - namespace, name, err := cache.SplitMetaNamespaceKey(key) - if err != nil { - logger.Errorf("invalid resource key: %s", key) - return nil - } - // Establish whether we are the leader for use below. - isLeader := r.IsLeaderFor(types.NamespacedName{ - Namespace: namespace, - Name: name, - }) - roi, isROI := r.reconciler.(ReadOnlyInterface) - rof, isROF := r.reconciler.(ReadOnlyFinalizer) - if !isLeader && !isROI && !isROF { - // If we are not the leader, and we don't implement either ReadOnly - // interface, then take a fast-path out. - return nil - } - - // If configStore is set, attach the frozen configuration to the context. - if r.configStore != nil { - ctx = r.configStore.ToContext(ctx) - } - - // Add the recorder to context. - ctx = controller.WithEventRecorder(ctx, r.Recorder) - - // Get the resource with this namespace/name. - - getter := r.Lister.CloudAuditLogsSources(namespace) - - original, err := getter.Get(name) - - if errors.IsNotFound(err) { - // The resource may no longer exist, in which case we stop processing. - logger.Debugf("resource %q no longer exists", key) - return nil - } else if err != nil { - return err - } - - // Don't modify the informers copy. - resource := original.DeepCopy() - - var reconcileEvent reconciler.Event - if resource.GetDeletionTimestamp().IsZero() { - if isLeader { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ReconcileKind")) - - // Set and update the finalizer on resource if r.reconciler - // implements Finalizer. - if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil { - return fmt.Errorf("failed to set finalizers: %w", err) - } - - reconciler.PreProcessReconcile(ctx, resource) - - // Reconcile this copy of the resource and then write back any status - // updates regardless of whether the reconciliation errored out. - reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) - - reconciler.PostProcessReconcile(ctx, resource, original) - - } else if isROI { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveKind")) - - // Observe any changes to this resource, since we are not the leader. - reconcileEvent = roi.ObserveKind(ctx, resource) - } - } else if fin, ok := r.reconciler.(Finalizer); isLeader && ok { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "FinalizeKind")) - - // For finalizing reconcilers, if this resource being marked for deletion - // and reconciled cleanly (nil or normal event), remove the finalizer. - reconcileEvent = fin.FinalizeKind(ctx, resource) - if resource, err = r.clearFinalizer(ctx, resource, reconcileEvent); err != nil { - return fmt.Errorf("failed to clear finalizers: %w", err) - } - } else if !isLeader && isROF { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveFinalizeKind")) - - // For finalizing reconcilers, just observe when we aren't the leader. - reconcileEvent = rof.ObserveFinalizeKind(ctx, resource) - } - - // Synchronize the status. - if equality.Semantic.DeepEqual(original.Status, resource.Status) { - // If we didn't change anything then don't call updateStatus. - // This is important because the copy we loaded from the injectionInformer's - // cache may be stale and we don't want to overwrite a prior update - // to status with this stale state. - } else if !isLeader { - logger.Warn("Saw status changes when we aren't the leader!") - // TODO: Consider logging the diff at Debug? - } else if err = r.updateStatus(original, resource); err != nil { - logger.Warnw("Failed to update resource status", zap.Error(err)) - r.Recorder.Eventf(resource, v1.EventTypeWarning, "UpdateFailed", - "Failed to update status for %q: %v", resource.Name, err) - return err - } - - // Report the reconciler event, if any. - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - logger.Infow("Returned an event", zap.Any("event", reconcileEvent)) - r.Recorder.Eventf(resource, event.EventType, event.Reason, event.Format, event.Args...) - - // the event was wrapped inside an error, consider the reconciliation as failed - if _, isEvent := reconcileEvent.(*reconciler.ReconcilerEvent); !isEvent { - return reconcileEvent - } - return nil - } - - logger.Errorw("Returned an error", zap.Error(reconcileEvent)) - r.Recorder.Event(resource, v1.EventTypeWarning, "InternalError", reconcileEvent.Error()) - return reconcileEvent - } - - return nil -} - -func (r *reconcilerImpl) updateStatus(existing *v1alpha1.CloudAuditLogsSource, desired *v1alpha1.CloudAuditLogsSource) error { - existing = existing.DeepCopy() - return reconciler.RetryUpdateConflicts(func(attempts int) (err error) { - // The first iteration tries to use the injectionInformer's state, subsequent attempts fetch the latest state via API. - if attempts > 0 { - - getter := r.Client.EventsV1alpha1().CloudAuditLogsSources(desired.Namespace) - - existing, err = getter.Get(desired.Name, metav1.GetOptions{}) - if err != nil { - return err - } - } - - // If there's nothing to update, just return. - if reflect.DeepEqual(existing.Status, desired.Status) { - return nil - } - - existing.Status = desired.Status - - updater := r.Client.EventsV1alpha1().CloudAuditLogsSources(existing.Namespace) - - _, err = updater.UpdateStatus(existing) - return err - }) -} - -// updateFinalizersFiltered will update the Finalizers of the resource. -// TODO: this method could be generic and sync all finalizers. For now it only -// updates defaultFinalizerName or its override. -func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource *v1alpha1.CloudAuditLogsSource) (*v1alpha1.CloudAuditLogsSource, error) { - - getter := r.Lister.CloudAuditLogsSources(resource.Namespace) - - actual, err := getter.Get(resource.Name) - if err != nil { - return resource, err - } - - // Don't modify the informers copy. - existing := actual.DeepCopy() - - var finalizers []string - - // If there's nothing to update, just return. - existingFinalizers := sets.NewString(existing.Finalizers...) - desiredFinalizers := sets.NewString(resource.Finalizers...) - - if desiredFinalizers.Has(r.finalizerName) { - if existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Add the finalizer. - finalizers = append(existing.Finalizers, r.finalizerName) - } else { - if !existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Remove the finalizer. - existingFinalizers.Delete(r.finalizerName) - finalizers = existingFinalizers.List() - } - - mergePatch := map[string]interface{}{ - "metadata": map[string]interface{}{ - "finalizers": finalizers, - "resourceVersion": existing.ResourceVersion, - }, - } - - patch, err := json.Marshal(mergePatch) - if err != nil { - return resource, err - } - - patcher := r.Client.EventsV1alpha1().CloudAuditLogsSources(resource.Namespace) - - resourceName := resource.Name - resource, err = patcher.Patch(resourceName, types.MergePatchType, patch) - if err != nil { - r.Recorder.Eventf(resource, v1.EventTypeWarning, "FinalizerUpdateFailed", - "Failed to update finalizers for %q: %v", resourceName, err) - } else { - r.Recorder.Eventf(resource, v1.EventTypeNormal, "FinalizerUpdate", - "Updated %q finalizers", resource.GetName()) - } - return resource, err -} - -func (r *reconcilerImpl) setFinalizerIfFinalizer(ctx context.Context, resource *v1alpha1.CloudAuditLogsSource) (*v1alpha1.CloudAuditLogsSource, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - // If this resource is not being deleted, mark the finalizer. - if resource.GetDeletionTimestamp().IsZero() { - finalizers.Insert(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} - -func (r *reconcilerImpl) clearFinalizer(ctx context.Context, resource *v1alpha1.CloudAuditLogsSource, reconcileEvent reconciler.Event) (*v1alpha1.CloudAuditLogsSource, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - if resource.GetDeletionTimestamp().IsZero() { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - if event.EventType == v1.EventTypeNormal { - finalizers.Delete(r.finalizerName) - } - } - } else { - finalizers.Delete(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/stub/controller.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/stub/controller.go deleted file mode 100644 index e4c292ddea..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/stub/controller.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudauditlogssource - -import ( - context "context" - - cloudauditlogssource "github.com/google/knative-gcp/pkg/client/injection/informers/events/v1alpha1/cloudauditlogssource" - v1alpha1cloudauditlogssource "github.com/google/knative-gcp/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource" - configmap "knative.dev/pkg/configmap" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// NewController creates a Reconciler for CloudAuditLogsSource and returns the result of NewImpl. -func NewController( - ctx context.Context, - cmw configmap.Watcher, -) *controller.Impl { - logger := logging.FromContext(ctx) - - cloudauditlogssourceInformer := cloudauditlogssource.Get(ctx) - - // TODO: setup additional informers here. - - r := &Reconciler{} - impl := v1alpha1cloudauditlogssource.NewImpl(ctx, r) - - logger.Info("Setting up event handlers.") - - cloudauditlogssourceInformer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue)) - - // TODO: add additional informer event handlers here. - - return impl -} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/stub/reconciler.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/stub/reconciler.go deleted file mode 100644 index 4ad50dc87f..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource/stub/reconciler.go +++ /dev/null @@ -1,87 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudauditlogssource - -import ( - context "context" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" - cloudauditlogssource "github.com/google/knative-gcp/pkg/client/injection/reconciler/events/v1alpha1/cloudauditlogssource" - v1 "k8s.io/api/core/v1" - reconciler "knative.dev/pkg/reconciler" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// newReconciledNormal makes a new reconciler event with event type Normal, and -// reason CloudAuditLogsSourceReconciled. -func newReconciledNormal(namespace, name string) reconciler.Event { - return reconciler.NewEvent(v1.EventTypeNormal, "CloudAuditLogsSourceReconciled", "CloudAuditLogsSource reconciled: \"%s/%s\"", namespace, name) -} - -// Reconciler implements controller.Reconciler for CloudAuditLogsSource resources. -type Reconciler struct { - // TODO: add additional requirements here. -} - -// Check that our Reconciler implements Interface -var _ cloudauditlogssource.Interface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements Finalizer -//var _ cloudauditlogssource.Finalizer = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyInterface -// Implement this to observe resources even when we are not the leader. -//var _ cloudauditlogssource.ReadOnlyInterface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyFinalizer -// Implement this to observe tombstoned resources even when we are not -// the leader (best effort). -//var _ cloudauditlogssource.ReadOnlyFinalizer = (*Reconciler)(nil) - -// ReconcileKind implements Interface.ReconcileKind. -func (r *Reconciler) ReconcileKind(ctx context.Context, o *v1alpha1.CloudAuditLogsSource) reconciler.Event { - // TODO: use this if the resource implements InitializeConditions. - // o.Status.InitializeConditions() - - // TODO: add custom reconciliation logic here. - - // TODO: use this if the object has .status.ObservedGeneration. - // o.Status.ObservedGeneration = o.Generation - return newReconciledNormal(o.Namespace, o.Name) -} - -// Optionally, use FinalizeKind to add finalizers. FinalizeKind will be called -// when the resource is deleted. -//func (r *Reconciler) FinalizeKind(ctx context.Context, o *v1alpha1.CloudAuditLogsSource) reconciler.Event { -// // TODO: add custom finalization logic here. -// return nil -//} - -// Optionally, use ObserveKind to observe the resource when we are not the leader. -// func (r *Reconciler) ObserveKind(ctx context.Context, o *v1alpha1.CloudAuditLogsSource) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -// } - -// Optionally, use ObserveFinalizeKind to observe resources being finalized when we are no the leader. -//func (r *Reconciler) ObserveFinalizeKind(ctx context.Context, o *v1alpha1.CloudAuditLogsSource) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -//} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/controller.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/controller.go deleted file mode 100644 index 6fce4038c2..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/controller.go +++ /dev/null @@ -1,139 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudbuildsource - -import ( - context "context" - fmt "fmt" - reflect "reflect" - strings "strings" - - versionedscheme "github.com/google/knative-gcp/pkg/client/clientset/versioned/scheme" - client "github.com/google/knative-gcp/pkg/client/injection/client" - cloudbuildsource "github.com/google/knative-gcp/pkg/client/injection/informers/events/v1alpha1/cloudbuildsource" - corev1 "k8s.io/api/core/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - scheme "k8s.io/client-go/kubernetes/scheme" - v1 "k8s.io/client-go/kubernetes/typed/core/v1" - record "k8s.io/client-go/tools/record" - kubeclient "knative.dev/pkg/client/injection/kube/client" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -const ( - defaultControllerAgentName = "cloudbuildsource-controller" - defaultFinalizerName = "cloudbuildsources.events.cloud.google.com" -) - -// NewImpl returns a controller.Impl that handles queuing and feeding work from -// the queue through an implementation of controller.Reconciler, delegating to -// the provided Interface and optional Finalizer methods. OptionsFn is used to return -// controller.Options to be used but the internal reconciler. -func NewImpl(ctx context.Context, r Interface, optionsFns ...controller.OptionsFn) *controller.Impl { - logger := logging.FromContext(ctx) - - // Check the options function input. It should be 0 or 1. - if len(optionsFns) > 1 { - logger.Fatalf("up to one options function is supported, found %d", len(optionsFns)) - } - - cloudbuildsourceInformer := cloudbuildsource.Get(ctx) - - lister := cloudbuildsourceInformer.Lister() - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client.Get(ctx), - Lister: lister, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - t := reflect.TypeOf(r).Elem() - queueName := fmt.Sprintf("%s.%s", strings.ReplaceAll(t.PkgPath(), "/", "-"), t.Name()) - - impl := controller.NewImpl(rec, logger, queueName) - agentName := defaultControllerAgentName - - // Pass impl to the options. Save any optional results. - for _, fn := range optionsFns { - opts := fn(impl) - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - if opts.AgentName != "" { - agentName = opts.AgentName - } - } - - rec.Recorder = createRecorder(ctx, agentName) - - return impl -} - -func createRecorder(ctx context.Context, agentName string) record.EventRecorder { - logger := logging.FromContext(ctx) - - recorder := controller.GetEventRecorder(ctx) - if recorder == nil { - // Create event broadcaster - logger.Debug("Creating event broadcaster") - eventBroadcaster := record.NewBroadcaster() - watches := []watch.Interface{ - eventBroadcaster.StartLogging(logger.Named("event-broadcaster").Infof), - eventBroadcaster.StartRecordingToSink( - &v1.EventSinkImpl{Interface: kubeclient.Get(ctx).CoreV1().Events("")}), - } - recorder = eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: agentName}) - go func() { - <-ctx.Done() - for _, w := range watches { - w.Stop() - } - }() - } - - return recorder -} - -func init() { - versionedscheme.AddToScheme(scheme.Scheme) -} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/reconciler.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/reconciler.go deleted file mode 100644 index f830d31219..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/reconciler.go +++ /dev/null @@ -1,434 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudbuildsource - -import ( - context "context" - json "encoding/json" - fmt "fmt" - reflect "reflect" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" - versioned "github.com/google/knative-gcp/pkg/client/clientset/versioned" - eventsv1alpha1 "github.com/google/knative-gcp/pkg/client/listers/events/v1alpha1" - zap "go.uber.org/zap" - v1 "k8s.io/api/core/v1" - equality "k8s.io/apimachinery/pkg/api/equality" - errors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - sets "k8s.io/apimachinery/pkg/util/sets" - cache "k8s.io/client-go/tools/cache" - record "k8s.io/client-go/tools/record" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -// Interface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.CloudBuildSource. -type Interface interface { - // ReconcileKind implements custom logic to reconcile v1alpha1.CloudBuildSource. Any changes - // to the objects .Status or .Finalizers will be propagated to the stored - // object. It is recommended that implementors do not call any update calls - // for the Kind inside of ReconcileKind, it is the responsibility of the calling - // controller to propagate those properties. The resource passed to ReconcileKind - // will always have an empty deletion timestamp. - ReconcileKind(ctx context.Context, o *v1alpha1.CloudBuildSource) reconciler.Event -} - -// Finalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.CloudBuildSource. -type Finalizer interface { - // FinalizeKind implements custom logic to finalize v1alpha1.CloudBuildSource. Any changes - // to the objects .Status or .Finalizers will be ignored. Returning a nil or - // Normal type reconciler.Event will allow the finalizer to be deleted on - // the resource. The resource passed to FinalizeKind will always have a set - // deletion timestamp. - FinalizeKind(ctx context.Context, o *v1alpha1.CloudBuildSource) reconciler.Event -} - -// ReadOnlyInterface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.CloudBuildSource if they want to process resources for which -// they are not the leader. -type ReadOnlyInterface interface { - // ObserveKind implements logic to observe v1alpha1.CloudBuildSource. - // This method should not write to the API. - ObserveKind(ctx context.Context, o *v1alpha1.CloudBuildSource) reconciler.Event -} - -// ReadOnlyFinalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.CloudBuildSource if they want to process tombstoned resources -// even when they are not the leader. Due to the nature of how finalizers are handled -// there are no guarantees that this will be called. -type ReadOnlyFinalizer interface { - // ObserveFinalizeKind implements custom logic to observe the final state of v1alpha1.CloudBuildSource. - // This method should not write to the API. - ObserveFinalizeKind(ctx context.Context, o *v1alpha1.CloudBuildSource) reconciler.Event -} - -// reconcilerImpl implements controller.Reconciler for v1alpha1.CloudBuildSource resources. -type reconcilerImpl struct { - // LeaderAwareFuncs is inlined to help us implement reconciler.LeaderAware - reconciler.LeaderAwareFuncs - - // Client is used to write back status updates. - Client versioned.Interface - - // Listers index properties about resources - Lister eventsv1alpha1.CloudBuildSourceLister - - // Recorder is an event recorder for recording Event resources to the - // Kubernetes API. - Recorder record.EventRecorder - - // configStore allows for decorating a context with config maps. - // +optional - configStore reconciler.ConfigStore - - // reconciler is the implementation of the business logic of the resource. - reconciler Interface - - // finalizerName is the name of the finalizer to reconcile. - finalizerName string -} - -// Check that our Reconciler implements controller.Reconciler -var _ controller.Reconciler = (*reconcilerImpl)(nil) - -// Check that our generated Reconciler is always LeaderAware. -var _ reconciler.LeaderAware = (*reconcilerImpl)(nil) - -func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versioned.Interface, lister eventsv1alpha1.CloudBuildSourceLister, recorder record.EventRecorder, r Interface, options ...controller.Options) controller.Reconciler { - // Check the options function input. It should be 0 or 1. - if len(options) > 1 { - logger.Fatalf("up to one options struct is supported, found %d", len(options)) - } - - // Fail fast when users inadvertently implement the other LeaderAware interface. - // For the typed reconcilers, Promote shouldn't take any arguments. - if _, ok := r.(reconciler.LeaderAware); ok { - logger.Fatalf("%T implements the incorrect LeaderAware interface. Promote() should not take an argument as genreconciler handles the enqueuing automatically.", r) - } - // TODO: Consider validating when folks implement ReadOnlyFinalizer, but not Finalizer. - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client, - Lister: lister, - Recorder: recorder, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - for _, opts := range options { - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - } - - return rec -} - -// Reconcile implements controller.Reconciler -func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { - logger := logging.FromContext(ctx) - - // Convert the namespace/name string into a distinct namespace and name - namespace, name, err := cache.SplitMetaNamespaceKey(key) - if err != nil { - logger.Errorf("invalid resource key: %s", key) - return nil - } - // Establish whether we are the leader for use below. - isLeader := r.IsLeaderFor(types.NamespacedName{ - Namespace: namespace, - Name: name, - }) - roi, isROI := r.reconciler.(ReadOnlyInterface) - rof, isROF := r.reconciler.(ReadOnlyFinalizer) - if !isLeader && !isROI && !isROF { - // If we are not the leader, and we don't implement either ReadOnly - // interface, then take a fast-path out. - return nil - } - - // If configStore is set, attach the frozen configuration to the context. - if r.configStore != nil { - ctx = r.configStore.ToContext(ctx) - } - - // Add the recorder to context. - ctx = controller.WithEventRecorder(ctx, r.Recorder) - - // Get the resource with this namespace/name. - - getter := r.Lister.CloudBuildSources(namespace) - - original, err := getter.Get(name) - - if errors.IsNotFound(err) { - // The resource may no longer exist, in which case we stop processing. - logger.Debugf("resource %q no longer exists", key) - return nil - } else if err != nil { - return err - } - - // Don't modify the informers copy. - resource := original.DeepCopy() - - var reconcileEvent reconciler.Event - if resource.GetDeletionTimestamp().IsZero() { - if isLeader { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ReconcileKind")) - - // Set and update the finalizer on resource if r.reconciler - // implements Finalizer. - if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil { - return fmt.Errorf("failed to set finalizers: %w", err) - } - - reconciler.PreProcessReconcile(ctx, resource) - - // Reconcile this copy of the resource and then write back any status - // updates regardless of whether the reconciliation errored out. - reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) - - reconciler.PostProcessReconcile(ctx, resource, original) - - } else if isROI { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveKind")) - - // Observe any changes to this resource, since we are not the leader. - reconcileEvent = roi.ObserveKind(ctx, resource) - } - } else if fin, ok := r.reconciler.(Finalizer); isLeader && ok { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "FinalizeKind")) - - // For finalizing reconcilers, if this resource being marked for deletion - // and reconciled cleanly (nil or normal event), remove the finalizer. - reconcileEvent = fin.FinalizeKind(ctx, resource) - if resource, err = r.clearFinalizer(ctx, resource, reconcileEvent); err != nil { - return fmt.Errorf("failed to clear finalizers: %w", err) - } - } else if !isLeader && isROF { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveFinalizeKind")) - - // For finalizing reconcilers, just observe when we aren't the leader. - reconcileEvent = rof.ObserveFinalizeKind(ctx, resource) - } - - // Synchronize the status. - if equality.Semantic.DeepEqual(original.Status, resource.Status) { - // If we didn't change anything then don't call updateStatus. - // This is important because the copy we loaded from the injectionInformer's - // cache may be stale and we don't want to overwrite a prior update - // to status with this stale state. - } else if !isLeader { - logger.Warn("Saw status changes when we aren't the leader!") - // TODO: Consider logging the diff at Debug? - } else if err = r.updateStatus(original, resource); err != nil { - logger.Warnw("Failed to update resource status", zap.Error(err)) - r.Recorder.Eventf(resource, v1.EventTypeWarning, "UpdateFailed", - "Failed to update status for %q: %v", resource.Name, err) - return err - } - - // Report the reconciler event, if any. - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - logger.Infow("Returned an event", zap.Any("event", reconcileEvent)) - r.Recorder.Eventf(resource, event.EventType, event.Reason, event.Format, event.Args...) - - // the event was wrapped inside an error, consider the reconciliation as failed - if _, isEvent := reconcileEvent.(*reconciler.ReconcilerEvent); !isEvent { - return reconcileEvent - } - return nil - } - - logger.Errorw("Returned an error", zap.Error(reconcileEvent)) - r.Recorder.Event(resource, v1.EventTypeWarning, "InternalError", reconcileEvent.Error()) - return reconcileEvent - } - - return nil -} - -func (r *reconcilerImpl) updateStatus(existing *v1alpha1.CloudBuildSource, desired *v1alpha1.CloudBuildSource) error { - existing = existing.DeepCopy() - return reconciler.RetryUpdateConflicts(func(attempts int) (err error) { - // The first iteration tries to use the injectionInformer's state, subsequent attempts fetch the latest state via API. - if attempts > 0 { - - getter := r.Client.EventsV1alpha1().CloudBuildSources(desired.Namespace) - - existing, err = getter.Get(desired.Name, metav1.GetOptions{}) - if err != nil { - return err - } - } - - // If there's nothing to update, just return. - if reflect.DeepEqual(existing.Status, desired.Status) { - return nil - } - - existing.Status = desired.Status - - updater := r.Client.EventsV1alpha1().CloudBuildSources(existing.Namespace) - - _, err = updater.UpdateStatus(existing) - return err - }) -} - -// updateFinalizersFiltered will update the Finalizers of the resource. -// TODO: this method could be generic and sync all finalizers. For now it only -// updates defaultFinalizerName or its override. -func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource *v1alpha1.CloudBuildSource) (*v1alpha1.CloudBuildSource, error) { - - getter := r.Lister.CloudBuildSources(resource.Namespace) - - actual, err := getter.Get(resource.Name) - if err != nil { - return resource, err - } - - // Don't modify the informers copy. - existing := actual.DeepCopy() - - var finalizers []string - - // If there's nothing to update, just return. - existingFinalizers := sets.NewString(existing.Finalizers...) - desiredFinalizers := sets.NewString(resource.Finalizers...) - - if desiredFinalizers.Has(r.finalizerName) { - if existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Add the finalizer. - finalizers = append(existing.Finalizers, r.finalizerName) - } else { - if !existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Remove the finalizer. - existingFinalizers.Delete(r.finalizerName) - finalizers = existingFinalizers.List() - } - - mergePatch := map[string]interface{}{ - "metadata": map[string]interface{}{ - "finalizers": finalizers, - "resourceVersion": existing.ResourceVersion, - }, - } - - patch, err := json.Marshal(mergePatch) - if err != nil { - return resource, err - } - - patcher := r.Client.EventsV1alpha1().CloudBuildSources(resource.Namespace) - - resourceName := resource.Name - resource, err = patcher.Patch(resourceName, types.MergePatchType, patch) - if err != nil { - r.Recorder.Eventf(resource, v1.EventTypeWarning, "FinalizerUpdateFailed", - "Failed to update finalizers for %q: %v", resourceName, err) - } else { - r.Recorder.Eventf(resource, v1.EventTypeNormal, "FinalizerUpdate", - "Updated %q finalizers", resource.GetName()) - } - return resource, err -} - -func (r *reconcilerImpl) setFinalizerIfFinalizer(ctx context.Context, resource *v1alpha1.CloudBuildSource) (*v1alpha1.CloudBuildSource, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - // If this resource is not being deleted, mark the finalizer. - if resource.GetDeletionTimestamp().IsZero() { - finalizers.Insert(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} - -func (r *reconcilerImpl) clearFinalizer(ctx context.Context, resource *v1alpha1.CloudBuildSource, reconcileEvent reconciler.Event) (*v1alpha1.CloudBuildSource, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - if resource.GetDeletionTimestamp().IsZero() { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - if event.EventType == v1.EventTypeNormal { - finalizers.Delete(r.finalizerName) - } - } - } else { - finalizers.Delete(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/stub/controller.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/stub/controller.go deleted file mode 100644 index 224fa83c1d..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/stub/controller.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudbuildsource - -import ( - context "context" - - cloudbuildsource "github.com/google/knative-gcp/pkg/client/injection/informers/events/v1alpha1/cloudbuildsource" - v1alpha1cloudbuildsource "github.com/google/knative-gcp/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource" - configmap "knative.dev/pkg/configmap" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// NewController creates a Reconciler for CloudBuildSource and returns the result of NewImpl. -func NewController( - ctx context.Context, - cmw configmap.Watcher, -) *controller.Impl { - logger := logging.FromContext(ctx) - - cloudbuildsourceInformer := cloudbuildsource.Get(ctx) - - // TODO: setup additional informers here. - - r := &Reconciler{} - impl := v1alpha1cloudbuildsource.NewImpl(ctx, r) - - logger.Info("Setting up event handlers.") - - cloudbuildsourceInformer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue)) - - // TODO: add additional informer event handlers here. - - return impl -} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/stub/reconciler.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/stub/reconciler.go deleted file mode 100644 index ca34968718..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource/stub/reconciler.go +++ /dev/null @@ -1,87 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudbuildsource - -import ( - context "context" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" - cloudbuildsource "github.com/google/knative-gcp/pkg/client/injection/reconciler/events/v1alpha1/cloudbuildsource" - v1 "k8s.io/api/core/v1" - reconciler "knative.dev/pkg/reconciler" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// newReconciledNormal makes a new reconciler event with event type Normal, and -// reason CloudBuildSourceReconciled. -func newReconciledNormal(namespace, name string) reconciler.Event { - return reconciler.NewEvent(v1.EventTypeNormal, "CloudBuildSourceReconciled", "CloudBuildSource reconciled: \"%s/%s\"", namespace, name) -} - -// Reconciler implements controller.Reconciler for CloudBuildSource resources. -type Reconciler struct { - // TODO: add additional requirements here. -} - -// Check that our Reconciler implements Interface -var _ cloudbuildsource.Interface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements Finalizer -//var _ cloudbuildsource.Finalizer = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyInterface -// Implement this to observe resources even when we are not the leader. -//var _ cloudbuildsource.ReadOnlyInterface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyFinalizer -// Implement this to observe tombstoned resources even when we are not -// the leader (best effort). -//var _ cloudbuildsource.ReadOnlyFinalizer = (*Reconciler)(nil) - -// ReconcileKind implements Interface.ReconcileKind. -func (r *Reconciler) ReconcileKind(ctx context.Context, o *v1alpha1.CloudBuildSource) reconciler.Event { - // TODO: use this if the resource implements InitializeConditions. - // o.Status.InitializeConditions() - - // TODO: add custom reconciliation logic here. - - // TODO: use this if the object has .status.ObservedGeneration. - // o.Status.ObservedGeneration = o.Generation - return newReconciledNormal(o.Namespace, o.Name) -} - -// Optionally, use FinalizeKind to add finalizers. FinalizeKind will be called -// when the resource is deleted. -//func (r *Reconciler) FinalizeKind(ctx context.Context, o *v1alpha1.CloudBuildSource) reconciler.Event { -// // TODO: add custom finalization logic here. -// return nil -//} - -// Optionally, use ObserveKind to observe the resource when we are not the leader. -// func (r *Reconciler) ObserveKind(ctx context.Context, o *v1alpha1.CloudBuildSource) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -// } - -// Optionally, use ObserveFinalizeKind to observe resources being finalized when we are no the leader. -//func (r *Reconciler) ObserveFinalizeKind(ctx context.Context, o *v1alpha1.CloudBuildSource) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -//} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/controller.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/controller.go deleted file mode 100644 index 1e5311d9b4..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/controller.go +++ /dev/null @@ -1,139 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudpubsubsource - -import ( - context "context" - fmt "fmt" - reflect "reflect" - strings "strings" - - versionedscheme "github.com/google/knative-gcp/pkg/client/clientset/versioned/scheme" - client "github.com/google/knative-gcp/pkg/client/injection/client" - cloudpubsubsource "github.com/google/knative-gcp/pkg/client/injection/informers/events/v1alpha1/cloudpubsubsource" - corev1 "k8s.io/api/core/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - scheme "k8s.io/client-go/kubernetes/scheme" - v1 "k8s.io/client-go/kubernetes/typed/core/v1" - record "k8s.io/client-go/tools/record" - kubeclient "knative.dev/pkg/client/injection/kube/client" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -const ( - defaultControllerAgentName = "cloudpubsubsource-controller" - defaultFinalizerName = "cloudpubsubsources.events.cloud.google.com" -) - -// NewImpl returns a controller.Impl that handles queuing and feeding work from -// the queue through an implementation of controller.Reconciler, delegating to -// the provided Interface and optional Finalizer methods. OptionsFn is used to return -// controller.Options to be used but the internal reconciler. -func NewImpl(ctx context.Context, r Interface, optionsFns ...controller.OptionsFn) *controller.Impl { - logger := logging.FromContext(ctx) - - // Check the options function input. It should be 0 or 1. - if len(optionsFns) > 1 { - logger.Fatalf("up to one options function is supported, found %d", len(optionsFns)) - } - - cloudpubsubsourceInformer := cloudpubsubsource.Get(ctx) - - lister := cloudpubsubsourceInformer.Lister() - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client.Get(ctx), - Lister: lister, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - t := reflect.TypeOf(r).Elem() - queueName := fmt.Sprintf("%s.%s", strings.ReplaceAll(t.PkgPath(), "/", "-"), t.Name()) - - impl := controller.NewImpl(rec, logger, queueName) - agentName := defaultControllerAgentName - - // Pass impl to the options. Save any optional results. - for _, fn := range optionsFns { - opts := fn(impl) - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - if opts.AgentName != "" { - agentName = opts.AgentName - } - } - - rec.Recorder = createRecorder(ctx, agentName) - - return impl -} - -func createRecorder(ctx context.Context, agentName string) record.EventRecorder { - logger := logging.FromContext(ctx) - - recorder := controller.GetEventRecorder(ctx) - if recorder == nil { - // Create event broadcaster - logger.Debug("Creating event broadcaster") - eventBroadcaster := record.NewBroadcaster() - watches := []watch.Interface{ - eventBroadcaster.StartLogging(logger.Named("event-broadcaster").Infof), - eventBroadcaster.StartRecordingToSink( - &v1.EventSinkImpl{Interface: kubeclient.Get(ctx).CoreV1().Events("")}), - } - recorder = eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: agentName}) - go func() { - <-ctx.Done() - for _, w := range watches { - w.Stop() - } - }() - } - - return recorder -} - -func init() { - versionedscheme.AddToScheme(scheme.Scheme) -} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/reconciler.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/reconciler.go deleted file mode 100644 index 0268d1dd72..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/reconciler.go +++ /dev/null @@ -1,434 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudpubsubsource - -import ( - context "context" - json "encoding/json" - fmt "fmt" - reflect "reflect" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" - versioned "github.com/google/knative-gcp/pkg/client/clientset/versioned" - eventsv1alpha1 "github.com/google/knative-gcp/pkg/client/listers/events/v1alpha1" - zap "go.uber.org/zap" - v1 "k8s.io/api/core/v1" - equality "k8s.io/apimachinery/pkg/api/equality" - errors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - sets "k8s.io/apimachinery/pkg/util/sets" - cache "k8s.io/client-go/tools/cache" - record "k8s.io/client-go/tools/record" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -// Interface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.CloudPubSubSource. -type Interface interface { - // ReconcileKind implements custom logic to reconcile v1alpha1.CloudPubSubSource. Any changes - // to the objects .Status or .Finalizers will be propagated to the stored - // object. It is recommended that implementors do not call any update calls - // for the Kind inside of ReconcileKind, it is the responsibility of the calling - // controller to propagate those properties. The resource passed to ReconcileKind - // will always have an empty deletion timestamp. - ReconcileKind(ctx context.Context, o *v1alpha1.CloudPubSubSource) reconciler.Event -} - -// Finalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.CloudPubSubSource. -type Finalizer interface { - // FinalizeKind implements custom logic to finalize v1alpha1.CloudPubSubSource. Any changes - // to the objects .Status or .Finalizers will be ignored. Returning a nil or - // Normal type reconciler.Event will allow the finalizer to be deleted on - // the resource. The resource passed to FinalizeKind will always have a set - // deletion timestamp. - FinalizeKind(ctx context.Context, o *v1alpha1.CloudPubSubSource) reconciler.Event -} - -// ReadOnlyInterface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.CloudPubSubSource if they want to process resources for which -// they are not the leader. -type ReadOnlyInterface interface { - // ObserveKind implements logic to observe v1alpha1.CloudPubSubSource. - // This method should not write to the API. - ObserveKind(ctx context.Context, o *v1alpha1.CloudPubSubSource) reconciler.Event -} - -// ReadOnlyFinalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.CloudPubSubSource if they want to process tombstoned resources -// even when they are not the leader. Due to the nature of how finalizers are handled -// there are no guarantees that this will be called. -type ReadOnlyFinalizer interface { - // ObserveFinalizeKind implements custom logic to observe the final state of v1alpha1.CloudPubSubSource. - // This method should not write to the API. - ObserveFinalizeKind(ctx context.Context, o *v1alpha1.CloudPubSubSource) reconciler.Event -} - -// reconcilerImpl implements controller.Reconciler for v1alpha1.CloudPubSubSource resources. -type reconcilerImpl struct { - // LeaderAwareFuncs is inlined to help us implement reconciler.LeaderAware - reconciler.LeaderAwareFuncs - - // Client is used to write back status updates. - Client versioned.Interface - - // Listers index properties about resources - Lister eventsv1alpha1.CloudPubSubSourceLister - - // Recorder is an event recorder for recording Event resources to the - // Kubernetes API. - Recorder record.EventRecorder - - // configStore allows for decorating a context with config maps. - // +optional - configStore reconciler.ConfigStore - - // reconciler is the implementation of the business logic of the resource. - reconciler Interface - - // finalizerName is the name of the finalizer to reconcile. - finalizerName string -} - -// Check that our Reconciler implements controller.Reconciler -var _ controller.Reconciler = (*reconcilerImpl)(nil) - -// Check that our generated Reconciler is always LeaderAware. -var _ reconciler.LeaderAware = (*reconcilerImpl)(nil) - -func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versioned.Interface, lister eventsv1alpha1.CloudPubSubSourceLister, recorder record.EventRecorder, r Interface, options ...controller.Options) controller.Reconciler { - // Check the options function input. It should be 0 or 1. - if len(options) > 1 { - logger.Fatalf("up to one options struct is supported, found %d", len(options)) - } - - // Fail fast when users inadvertently implement the other LeaderAware interface. - // For the typed reconcilers, Promote shouldn't take any arguments. - if _, ok := r.(reconciler.LeaderAware); ok { - logger.Fatalf("%T implements the incorrect LeaderAware interface. Promote() should not take an argument as genreconciler handles the enqueuing automatically.", r) - } - // TODO: Consider validating when folks implement ReadOnlyFinalizer, but not Finalizer. - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client, - Lister: lister, - Recorder: recorder, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - for _, opts := range options { - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - } - - return rec -} - -// Reconcile implements controller.Reconciler -func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { - logger := logging.FromContext(ctx) - - // Convert the namespace/name string into a distinct namespace and name - namespace, name, err := cache.SplitMetaNamespaceKey(key) - if err != nil { - logger.Errorf("invalid resource key: %s", key) - return nil - } - // Establish whether we are the leader for use below. - isLeader := r.IsLeaderFor(types.NamespacedName{ - Namespace: namespace, - Name: name, - }) - roi, isROI := r.reconciler.(ReadOnlyInterface) - rof, isROF := r.reconciler.(ReadOnlyFinalizer) - if !isLeader && !isROI && !isROF { - // If we are not the leader, and we don't implement either ReadOnly - // interface, then take a fast-path out. - return nil - } - - // If configStore is set, attach the frozen configuration to the context. - if r.configStore != nil { - ctx = r.configStore.ToContext(ctx) - } - - // Add the recorder to context. - ctx = controller.WithEventRecorder(ctx, r.Recorder) - - // Get the resource with this namespace/name. - - getter := r.Lister.CloudPubSubSources(namespace) - - original, err := getter.Get(name) - - if errors.IsNotFound(err) { - // The resource may no longer exist, in which case we stop processing. - logger.Debugf("resource %q no longer exists", key) - return nil - } else if err != nil { - return err - } - - // Don't modify the informers copy. - resource := original.DeepCopy() - - var reconcileEvent reconciler.Event - if resource.GetDeletionTimestamp().IsZero() { - if isLeader { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ReconcileKind")) - - // Set and update the finalizer on resource if r.reconciler - // implements Finalizer. - if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil { - return fmt.Errorf("failed to set finalizers: %w", err) - } - - reconciler.PreProcessReconcile(ctx, resource) - - // Reconcile this copy of the resource and then write back any status - // updates regardless of whether the reconciliation errored out. - reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) - - reconciler.PostProcessReconcile(ctx, resource, original) - - } else if isROI { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveKind")) - - // Observe any changes to this resource, since we are not the leader. - reconcileEvent = roi.ObserveKind(ctx, resource) - } - } else if fin, ok := r.reconciler.(Finalizer); isLeader && ok { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "FinalizeKind")) - - // For finalizing reconcilers, if this resource being marked for deletion - // and reconciled cleanly (nil or normal event), remove the finalizer. - reconcileEvent = fin.FinalizeKind(ctx, resource) - if resource, err = r.clearFinalizer(ctx, resource, reconcileEvent); err != nil { - return fmt.Errorf("failed to clear finalizers: %w", err) - } - } else if !isLeader && isROF { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveFinalizeKind")) - - // For finalizing reconcilers, just observe when we aren't the leader. - reconcileEvent = rof.ObserveFinalizeKind(ctx, resource) - } - - // Synchronize the status. - if equality.Semantic.DeepEqual(original.Status, resource.Status) { - // If we didn't change anything then don't call updateStatus. - // This is important because the copy we loaded from the injectionInformer's - // cache may be stale and we don't want to overwrite a prior update - // to status with this stale state. - } else if !isLeader { - logger.Warn("Saw status changes when we aren't the leader!") - // TODO: Consider logging the diff at Debug? - } else if err = r.updateStatus(original, resource); err != nil { - logger.Warnw("Failed to update resource status", zap.Error(err)) - r.Recorder.Eventf(resource, v1.EventTypeWarning, "UpdateFailed", - "Failed to update status for %q: %v", resource.Name, err) - return err - } - - // Report the reconciler event, if any. - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - logger.Infow("Returned an event", zap.Any("event", reconcileEvent)) - r.Recorder.Eventf(resource, event.EventType, event.Reason, event.Format, event.Args...) - - // the event was wrapped inside an error, consider the reconciliation as failed - if _, isEvent := reconcileEvent.(*reconciler.ReconcilerEvent); !isEvent { - return reconcileEvent - } - return nil - } - - logger.Errorw("Returned an error", zap.Error(reconcileEvent)) - r.Recorder.Event(resource, v1.EventTypeWarning, "InternalError", reconcileEvent.Error()) - return reconcileEvent - } - - return nil -} - -func (r *reconcilerImpl) updateStatus(existing *v1alpha1.CloudPubSubSource, desired *v1alpha1.CloudPubSubSource) error { - existing = existing.DeepCopy() - return reconciler.RetryUpdateConflicts(func(attempts int) (err error) { - // The first iteration tries to use the injectionInformer's state, subsequent attempts fetch the latest state via API. - if attempts > 0 { - - getter := r.Client.EventsV1alpha1().CloudPubSubSources(desired.Namespace) - - existing, err = getter.Get(desired.Name, metav1.GetOptions{}) - if err != nil { - return err - } - } - - // If there's nothing to update, just return. - if reflect.DeepEqual(existing.Status, desired.Status) { - return nil - } - - existing.Status = desired.Status - - updater := r.Client.EventsV1alpha1().CloudPubSubSources(existing.Namespace) - - _, err = updater.UpdateStatus(existing) - return err - }) -} - -// updateFinalizersFiltered will update the Finalizers of the resource. -// TODO: this method could be generic and sync all finalizers. For now it only -// updates defaultFinalizerName or its override. -func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource *v1alpha1.CloudPubSubSource) (*v1alpha1.CloudPubSubSource, error) { - - getter := r.Lister.CloudPubSubSources(resource.Namespace) - - actual, err := getter.Get(resource.Name) - if err != nil { - return resource, err - } - - // Don't modify the informers copy. - existing := actual.DeepCopy() - - var finalizers []string - - // If there's nothing to update, just return. - existingFinalizers := sets.NewString(existing.Finalizers...) - desiredFinalizers := sets.NewString(resource.Finalizers...) - - if desiredFinalizers.Has(r.finalizerName) { - if existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Add the finalizer. - finalizers = append(existing.Finalizers, r.finalizerName) - } else { - if !existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Remove the finalizer. - existingFinalizers.Delete(r.finalizerName) - finalizers = existingFinalizers.List() - } - - mergePatch := map[string]interface{}{ - "metadata": map[string]interface{}{ - "finalizers": finalizers, - "resourceVersion": existing.ResourceVersion, - }, - } - - patch, err := json.Marshal(mergePatch) - if err != nil { - return resource, err - } - - patcher := r.Client.EventsV1alpha1().CloudPubSubSources(resource.Namespace) - - resourceName := resource.Name - resource, err = patcher.Patch(resourceName, types.MergePatchType, patch) - if err != nil { - r.Recorder.Eventf(resource, v1.EventTypeWarning, "FinalizerUpdateFailed", - "Failed to update finalizers for %q: %v", resourceName, err) - } else { - r.Recorder.Eventf(resource, v1.EventTypeNormal, "FinalizerUpdate", - "Updated %q finalizers", resource.GetName()) - } - return resource, err -} - -func (r *reconcilerImpl) setFinalizerIfFinalizer(ctx context.Context, resource *v1alpha1.CloudPubSubSource) (*v1alpha1.CloudPubSubSource, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - // If this resource is not being deleted, mark the finalizer. - if resource.GetDeletionTimestamp().IsZero() { - finalizers.Insert(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} - -func (r *reconcilerImpl) clearFinalizer(ctx context.Context, resource *v1alpha1.CloudPubSubSource, reconcileEvent reconciler.Event) (*v1alpha1.CloudPubSubSource, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - if resource.GetDeletionTimestamp().IsZero() { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - if event.EventType == v1.EventTypeNormal { - finalizers.Delete(r.finalizerName) - } - } - } else { - finalizers.Delete(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/stub/controller.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/stub/controller.go deleted file mode 100644 index 80a186bf02..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/stub/controller.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudpubsubsource - -import ( - context "context" - - cloudpubsubsource "github.com/google/knative-gcp/pkg/client/injection/informers/events/v1alpha1/cloudpubsubsource" - v1alpha1cloudpubsubsource "github.com/google/knative-gcp/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource" - configmap "knative.dev/pkg/configmap" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// NewController creates a Reconciler for CloudPubSubSource and returns the result of NewImpl. -func NewController( - ctx context.Context, - cmw configmap.Watcher, -) *controller.Impl { - logger := logging.FromContext(ctx) - - cloudpubsubsourceInformer := cloudpubsubsource.Get(ctx) - - // TODO: setup additional informers here. - - r := &Reconciler{} - impl := v1alpha1cloudpubsubsource.NewImpl(ctx, r) - - logger.Info("Setting up event handlers.") - - cloudpubsubsourceInformer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue)) - - // TODO: add additional informer event handlers here. - - return impl -} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/stub/reconciler.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/stub/reconciler.go deleted file mode 100644 index b1696da828..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource/stub/reconciler.go +++ /dev/null @@ -1,87 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudpubsubsource - -import ( - context "context" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" - cloudpubsubsource "github.com/google/knative-gcp/pkg/client/injection/reconciler/events/v1alpha1/cloudpubsubsource" - v1 "k8s.io/api/core/v1" - reconciler "knative.dev/pkg/reconciler" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// newReconciledNormal makes a new reconciler event with event type Normal, and -// reason CloudPubSubSourceReconciled. -func newReconciledNormal(namespace, name string) reconciler.Event { - return reconciler.NewEvent(v1.EventTypeNormal, "CloudPubSubSourceReconciled", "CloudPubSubSource reconciled: \"%s/%s\"", namespace, name) -} - -// Reconciler implements controller.Reconciler for CloudPubSubSource resources. -type Reconciler struct { - // TODO: add additional requirements here. -} - -// Check that our Reconciler implements Interface -var _ cloudpubsubsource.Interface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements Finalizer -//var _ cloudpubsubsource.Finalizer = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyInterface -// Implement this to observe resources even when we are not the leader. -//var _ cloudpubsubsource.ReadOnlyInterface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyFinalizer -// Implement this to observe tombstoned resources even when we are not -// the leader (best effort). -//var _ cloudpubsubsource.ReadOnlyFinalizer = (*Reconciler)(nil) - -// ReconcileKind implements Interface.ReconcileKind. -func (r *Reconciler) ReconcileKind(ctx context.Context, o *v1alpha1.CloudPubSubSource) reconciler.Event { - // TODO: use this if the resource implements InitializeConditions. - // o.Status.InitializeConditions() - - // TODO: add custom reconciliation logic here. - - // TODO: use this if the object has .status.ObservedGeneration. - // o.Status.ObservedGeneration = o.Generation - return newReconciledNormal(o.Namespace, o.Name) -} - -// Optionally, use FinalizeKind to add finalizers. FinalizeKind will be called -// when the resource is deleted. -//func (r *Reconciler) FinalizeKind(ctx context.Context, o *v1alpha1.CloudPubSubSource) reconciler.Event { -// // TODO: add custom finalization logic here. -// return nil -//} - -// Optionally, use ObserveKind to observe the resource when we are not the leader. -// func (r *Reconciler) ObserveKind(ctx context.Context, o *v1alpha1.CloudPubSubSource) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -// } - -// Optionally, use ObserveFinalizeKind to observe resources being finalized when we are no the leader. -//func (r *Reconciler) ObserveFinalizeKind(ctx context.Context, o *v1alpha1.CloudPubSubSource) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -//} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/controller.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/controller.go deleted file mode 100644 index e350a053e7..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/controller.go +++ /dev/null @@ -1,139 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudschedulersource - -import ( - context "context" - fmt "fmt" - reflect "reflect" - strings "strings" - - versionedscheme "github.com/google/knative-gcp/pkg/client/clientset/versioned/scheme" - client "github.com/google/knative-gcp/pkg/client/injection/client" - cloudschedulersource "github.com/google/knative-gcp/pkg/client/injection/informers/events/v1alpha1/cloudschedulersource" - corev1 "k8s.io/api/core/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - scheme "k8s.io/client-go/kubernetes/scheme" - v1 "k8s.io/client-go/kubernetes/typed/core/v1" - record "k8s.io/client-go/tools/record" - kubeclient "knative.dev/pkg/client/injection/kube/client" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -const ( - defaultControllerAgentName = "cloudschedulersource-controller" - defaultFinalizerName = "cloudschedulersources.events.cloud.google.com" -) - -// NewImpl returns a controller.Impl that handles queuing and feeding work from -// the queue through an implementation of controller.Reconciler, delegating to -// the provided Interface and optional Finalizer methods. OptionsFn is used to return -// controller.Options to be used but the internal reconciler. -func NewImpl(ctx context.Context, r Interface, optionsFns ...controller.OptionsFn) *controller.Impl { - logger := logging.FromContext(ctx) - - // Check the options function input. It should be 0 or 1. - if len(optionsFns) > 1 { - logger.Fatalf("up to one options function is supported, found %d", len(optionsFns)) - } - - cloudschedulersourceInformer := cloudschedulersource.Get(ctx) - - lister := cloudschedulersourceInformer.Lister() - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client.Get(ctx), - Lister: lister, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - t := reflect.TypeOf(r).Elem() - queueName := fmt.Sprintf("%s.%s", strings.ReplaceAll(t.PkgPath(), "/", "-"), t.Name()) - - impl := controller.NewImpl(rec, logger, queueName) - agentName := defaultControllerAgentName - - // Pass impl to the options. Save any optional results. - for _, fn := range optionsFns { - opts := fn(impl) - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - if opts.AgentName != "" { - agentName = opts.AgentName - } - } - - rec.Recorder = createRecorder(ctx, agentName) - - return impl -} - -func createRecorder(ctx context.Context, agentName string) record.EventRecorder { - logger := logging.FromContext(ctx) - - recorder := controller.GetEventRecorder(ctx) - if recorder == nil { - // Create event broadcaster - logger.Debug("Creating event broadcaster") - eventBroadcaster := record.NewBroadcaster() - watches := []watch.Interface{ - eventBroadcaster.StartLogging(logger.Named("event-broadcaster").Infof), - eventBroadcaster.StartRecordingToSink( - &v1.EventSinkImpl{Interface: kubeclient.Get(ctx).CoreV1().Events("")}), - } - recorder = eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: agentName}) - go func() { - <-ctx.Done() - for _, w := range watches { - w.Stop() - } - }() - } - - return recorder -} - -func init() { - versionedscheme.AddToScheme(scheme.Scheme) -} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/reconciler.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/reconciler.go deleted file mode 100644 index 8a686a742f..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/reconciler.go +++ /dev/null @@ -1,434 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudschedulersource - -import ( - context "context" - json "encoding/json" - fmt "fmt" - reflect "reflect" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" - versioned "github.com/google/knative-gcp/pkg/client/clientset/versioned" - eventsv1alpha1 "github.com/google/knative-gcp/pkg/client/listers/events/v1alpha1" - zap "go.uber.org/zap" - v1 "k8s.io/api/core/v1" - equality "k8s.io/apimachinery/pkg/api/equality" - errors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - sets "k8s.io/apimachinery/pkg/util/sets" - cache "k8s.io/client-go/tools/cache" - record "k8s.io/client-go/tools/record" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -// Interface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.CloudSchedulerSource. -type Interface interface { - // ReconcileKind implements custom logic to reconcile v1alpha1.CloudSchedulerSource. Any changes - // to the objects .Status or .Finalizers will be propagated to the stored - // object. It is recommended that implementors do not call any update calls - // for the Kind inside of ReconcileKind, it is the responsibility of the calling - // controller to propagate those properties. The resource passed to ReconcileKind - // will always have an empty deletion timestamp. - ReconcileKind(ctx context.Context, o *v1alpha1.CloudSchedulerSource) reconciler.Event -} - -// Finalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.CloudSchedulerSource. -type Finalizer interface { - // FinalizeKind implements custom logic to finalize v1alpha1.CloudSchedulerSource. Any changes - // to the objects .Status or .Finalizers will be ignored. Returning a nil or - // Normal type reconciler.Event will allow the finalizer to be deleted on - // the resource. The resource passed to FinalizeKind will always have a set - // deletion timestamp. - FinalizeKind(ctx context.Context, o *v1alpha1.CloudSchedulerSource) reconciler.Event -} - -// ReadOnlyInterface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.CloudSchedulerSource if they want to process resources for which -// they are not the leader. -type ReadOnlyInterface interface { - // ObserveKind implements logic to observe v1alpha1.CloudSchedulerSource. - // This method should not write to the API. - ObserveKind(ctx context.Context, o *v1alpha1.CloudSchedulerSource) reconciler.Event -} - -// ReadOnlyFinalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.CloudSchedulerSource if they want to process tombstoned resources -// even when they are not the leader. Due to the nature of how finalizers are handled -// there are no guarantees that this will be called. -type ReadOnlyFinalizer interface { - // ObserveFinalizeKind implements custom logic to observe the final state of v1alpha1.CloudSchedulerSource. - // This method should not write to the API. - ObserveFinalizeKind(ctx context.Context, o *v1alpha1.CloudSchedulerSource) reconciler.Event -} - -// reconcilerImpl implements controller.Reconciler for v1alpha1.CloudSchedulerSource resources. -type reconcilerImpl struct { - // LeaderAwareFuncs is inlined to help us implement reconciler.LeaderAware - reconciler.LeaderAwareFuncs - - // Client is used to write back status updates. - Client versioned.Interface - - // Listers index properties about resources - Lister eventsv1alpha1.CloudSchedulerSourceLister - - // Recorder is an event recorder for recording Event resources to the - // Kubernetes API. - Recorder record.EventRecorder - - // configStore allows for decorating a context with config maps. - // +optional - configStore reconciler.ConfigStore - - // reconciler is the implementation of the business logic of the resource. - reconciler Interface - - // finalizerName is the name of the finalizer to reconcile. - finalizerName string -} - -// Check that our Reconciler implements controller.Reconciler -var _ controller.Reconciler = (*reconcilerImpl)(nil) - -// Check that our generated Reconciler is always LeaderAware. -var _ reconciler.LeaderAware = (*reconcilerImpl)(nil) - -func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versioned.Interface, lister eventsv1alpha1.CloudSchedulerSourceLister, recorder record.EventRecorder, r Interface, options ...controller.Options) controller.Reconciler { - // Check the options function input. It should be 0 or 1. - if len(options) > 1 { - logger.Fatalf("up to one options struct is supported, found %d", len(options)) - } - - // Fail fast when users inadvertently implement the other LeaderAware interface. - // For the typed reconcilers, Promote shouldn't take any arguments. - if _, ok := r.(reconciler.LeaderAware); ok { - logger.Fatalf("%T implements the incorrect LeaderAware interface. Promote() should not take an argument as genreconciler handles the enqueuing automatically.", r) - } - // TODO: Consider validating when folks implement ReadOnlyFinalizer, but not Finalizer. - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client, - Lister: lister, - Recorder: recorder, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - for _, opts := range options { - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - } - - return rec -} - -// Reconcile implements controller.Reconciler -func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { - logger := logging.FromContext(ctx) - - // Convert the namespace/name string into a distinct namespace and name - namespace, name, err := cache.SplitMetaNamespaceKey(key) - if err != nil { - logger.Errorf("invalid resource key: %s", key) - return nil - } - // Establish whether we are the leader for use below. - isLeader := r.IsLeaderFor(types.NamespacedName{ - Namespace: namespace, - Name: name, - }) - roi, isROI := r.reconciler.(ReadOnlyInterface) - rof, isROF := r.reconciler.(ReadOnlyFinalizer) - if !isLeader && !isROI && !isROF { - // If we are not the leader, and we don't implement either ReadOnly - // interface, then take a fast-path out. - return nil - } - - // If configStore is set, attach the frozen configuration to the context. - if r.configStore != nil { - ctx = r.configStore.ToContext(ctx) - } - - // Add the recorder to context. - ctx = controller.WithEventRecorder(ctx, r.Recorder) - - // Get the resource with this namespace/name. - - getter := r.Lister.CloudSchedulerSources(namespace) - - original, err := getter.Get(name) - - if errors.IsNotFound(err) { - // The resource may no longer exist, in which case we stop processing. - logger.Debugf("resource %q no longer exists", key) - return nil - } else if err != nil { - return err - } - - // Don't modify the informers copy. - resource := original.DeepCopy() - - var reconcileEvent reconciler.Event - if resource.GetDeletionTimestamp().IsZero() { - if isLeader { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ReconcileKind")) - - // Set and update the finalizer on resource if r.reconciler - // implements Finalizer. - if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil { - return fmt.Errorf("failed to set finalizers: %w", err) - } - - reconciler.PreProcessReconcile(ctx, resource) - - // Reconcile this copy of the resource and then write back any status - // updates regardless of whether the reconciliation errored out. - reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) - - reconciler.PostProcessReconcile(ctx, resource, original) - - } else if isROI { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveKind")) - - // Observe any changes to this resource, since we are not the leader. - reconcileEvent = roi.ObserveKind(ctx, resource) - } - } else if fin, ok := r.reconciler.(Finalizer); isLeader && ok { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "FinalizeKind")) - - // For finalizing reconcilers, if this resource being marked for deletion - // and reconciled cleanly (nil or normal event), remove the finalizer. - reconcileEvent = fin.FinalizeKind(ctx, resource) - if resource, err = r.clearFinalizer(ctx, resource, reconcileEvent); err != nil { - return fmt.Errorf("failed to clear finalizers: %w", err) - } - } else if !isLeader && isROF { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveFinalizeKind")) - - // For finalizing reconcilers, just observe when we aren't the leader. - reconcileEvent = rof.ObserveFinalizeKind(ctx, resource) - } - - // Synchronize the status. - if equality.Semantic.DeepEqual(original.Status, resource.Status) { - // If we didn't change anything then don't call updateStatus. - // This is important because the copy we loaded from the injectionInformer's - // cache may be stale and we don't want to overwrite a prior update - // to status with this stale state. - } else if !isLeader { - logger.Warn("Saw status changes when we aren't the leader!") - // TODO: Consider logging the diff at Debug? - } else if err = r.updateStatus(original, resource); err != nil { - logger.Warnw("Failed to update resource status", zap.Error(err)) - r.Recorder.Eventf(resource, v1.EventTypeWarning, "UpdateFailed", - "Failed to update status for %q: %v", resource.Name, err) - return err - } - - // Report the reconciler event, if any. - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - logger.Infow("Returned an event", zap.Any("event", reconcileEvent)) - r.Recorder.Eventf(resource, event.EventType, event.Reason, event.Format, event.Args...) - - // the event was wrapped inside an error, consider the reconciliation as failed - if _, isEvent := reconcileEvent.(*reconciler.ReconcilerEvent); !isEvent { - return reconcileEvent - } - return nil - } - - logger.Errorw("Returned an error", zap.Error(reconcileEvent)) - r.Recorder.Event(resource, v1.EventTypeWarning, "InternalError", reconcileEvent.Error()) - return reconcileEvent - } - - return nil -} - -func (r *reconcilerImpl) updateStatus(existing *v1alpha1.CloudSchedulerSource, desired *v1alpha1.CloudSchedulerSource) error { - existing = existing.DeepCopy() - return reconciler.RetryUpdateConflicts(func(attempts int) (err error) { - // The first iteration tries to use the injectionInformer's state, subsequent attempts fetch the latest state via API. - if attempts > 0 { - - getter := r.Client.EventsV1alpha1().CloudSchedulerSources(desired.Namespace) - - existing, err = getter.Get(desired.Name, metav1.GetOptions{}) - if err != nil { - return err - } - } - - // If there's nothing to update, just return. - if reflect.DeepEqual(existing.Status, desired.Status) { - return nil - } - - existing.Status = desired.Status - - updater := r.Client.EventsV1alpha1().CloudSchedulerSources(existing.Namespace) - - _, err = updater.UpdateStatus(existing) - return err - }) -} - -// updateFinalizersFiltered will update the Finalizers of the resource. -// TODO: this method could be generic and sync all finalizers. For now it only -// updates defaultFinalizerName or its override. -func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource *v1alpha1.CloudSchedulerSource) (*v1alpha1.CloudSchedulerSource, error) { - - getter := r.Lister.CloudSchedulerSources(resource.Namespace) - - actual, err := getter.Get(resource.Name) - if err != nil { - return resource, err - } - - // Don't modify the informers copy. - existing := actual.DeepCopy() - - var finalizers []string - - // If there's nothing to update, just return. - existingFinalizers := sets.NewString(existing.Finalizers...) - desiredFinalizers := sets.NewString(resource.Finalizers...) - - if desiredFinalizers.Has(r.finalizerName) { - if existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Add the finalizer. - finalizers = append(existing.Finalizers, r.finalizerName) - } else { - if !existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Remove the finalizer. - existingFinalizers.Delete(r.finalizerName) - finalizers = existingFinalizers.List() - } - - mergePatch := map[string]interface{}{ - "metadata": map[string]interface{}{ - "finalizers": finalizers, - "resourceVersion": existing.ResourceVersion, - }, - } - - patch, err := json.Marshal(mergePatch) - if err != nil { - return resource, err - } - - patcher := r.Client.EventsV1alpha1().CloudSchedulerSources(resource.Namespace) - - resourceName := resource.Name - resource, err = patcher.Patch(resourceName, types.MergePatchType, patch) - if err != nil { - r.Recorder.Eventf(resource, v1.EventTypeWarning, "FinalizerUpdateFailed", - "Failed to update finalizers for %q: %v", resourceName, err) - } else { - r.Recorder.Eventf(resource, v1.EventTypeNormal, "FinalizerUpdate", - "Updated %q finalizers", resource.GetName()) - } - return resource, err -} - -func (r *reconcilerImpl) setFinalizerIfFinalizer(ctx context.Context, resource *v1alpha1.CloudSchedulerSource) (*v1alpha1.CloudSchedulerSource, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - // If this resource is not being deleted, mark the finalizer. - if resource.GetDeletionTimestamp().IsZero() { - finalizers.Insert(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} - -func (r *reconcilerImpl) clearFinalizer(ctx context.Context, resource *v1alpha1.CloudSchedulerSource, reconcileEvent reconciler.Event) (*v1alpha1.CloudSchedulerSource, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - if resource.GetDeletionTimestamp().IsZero() { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - if event.EventType == v1.EventTypeNormal { - finalizers.Delete(r.finalizerName) - } - } - } else { - finalizers.Delete(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/stub/controller.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/stub/controller.go deleted file mode 100644 index f2df5e236d..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/stub/controller.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudschedulersource - -import ( - context "context" - - cloudschedulersource "github.com/google/knative-gcp/pkg/client/injection/informers/events/v1alpha1/cloudschedulersource" - v1alpha1cloudschedulersource "github.com/google/knative-gcp/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource" - configmap "knative.dev/pkg/configmap" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// NewController creates a Reconciler for CloudSchedulerSource and returns the result of NewImpl. -func NewController( - ctx context.Context, - cmw configmap.Watcher, -) *controller.Impl { - logger := logging.FromContext(ctx) - - cloudschedulersourceInformer := cloudschedulersource.Get(ctx) - - // TODO: setup additional informers here. - - r := &Reconciler{} - impl := v1alpha1cloudschedulersource.NewImpl(ctx, r) - - logger.Info("Setting up event handlers.") - - cloudschedulersourceInformer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue)) - - // TODO: add additional informer event handlers here. - - return impl -} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/stub/reconciler.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/stub/reconciler.go deleted file mode 100644 index 9d0e2604ee..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource/stub/reconciler.go +++ /dev/null @@ -1,87 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudschedulersource - -import ( - context "context" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" - cloudschedulersource "github.com/google/knative-gcp/pkg/client/injection/reconciler/events/v1alpha1/cloudschedulersource" - v1 "k8s.io/api/core/v1" - reconciler "knative.dev/pkg/reconciler" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// newReconciledNormal makes a new reconciler event with event type Normal, and -// reason CloudSchedulerSourceReconciled. -func newReconciledNormal(namespace, name string) reconciler.Event { - return reconciler.NewEvent(v1.EventTypeNormal, "CloudSchedulerSourceReconciled", "CloudSchedulerSource reconciled: \"%s/%s\"", namespace, name) -} - -// Reconciler implements controller.Reconciler for CloudSchedulerSource resources. -type Reconciler struct { - // TODO: add additional requirements here. -} - -// Check that our Reconciler implements Interface -var _ cloudschedulersource.Interface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements Finalizer -//var _ cloudschedulersource.Finalizer = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyInterface -// Implement this to observe resources even when we are not the leader. -//var _ cloudschedulersource.ReadOnlyInterface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyFinalizer -// Implement this to observe tombstoned resources even when we are not -// the leader (best effort). -//var _ cloudschedulersource.ReadOnlyFinalizer = (*Reconciler)(nil) - -// ReconcileKind implements Interface.ReconcileKind. -func (r *Reconciler) ReconcileKind(ctx context.Context, o *v1alpha1.CloudSchedulerSource) reconciler.Event { - // TODO: use this if the resource implements InitializeConditions. - // o.Status.InitializeConditions() - - // TODO: add custom reconciliation logic here. - - // TODO: use this if the object has .status.ObservedGeneration. - // o.Status.ObservedGeneration = o.Generation - return newReconciledNormal(o.Namespace, o.Name) -} - -// Optionally, use FinalizeKind to add finalizers. FinalizeKind will be called -// when the resource is deleted. -//func (r *Reconciler) FinalizeKind(ctx context.Context, o *v1alpha1.CloudSchedulerSource) reconciler.Event { -// // TODO: add custom finalization logic here. -// return nil -//} - -// Optionally, use ObserveKind to observe the resource when we are not the leader. -// func (r *Reconciler) ObserveKind(ctx context.Context, o *v1alpha1.CloudSchedulerSource) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -// } - -// Optionally, use ObserveFinalizeKind to observe resources being finalized when we are no the leader. -//func (r *Reconciler) ObserveFinalizeKind(ctx context.Context, o *v1alpha1.CloudSchedulerSource) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -//} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/controller.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/controller.go deleted file mode 100644 index 51dcfa63d1..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/controller.go +++ /dev/null @@ -1,139 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudstoragesource - -import ( - context "context" - fmt "fmt" - reflect "reflect" - strings "strings" - - versionedscheme "github.com/google/knative-gcp/pkg/client/clientset/versioned/scheme" - client "github.com/google/knative-gcp/pkg/client/injection/client" - cloudstoragesource "github.com/google/knative-gcp/pkg/client/injection/informers/events/v1alpha1/cloudstoragesource" - corev1 "k8s.io/api/core/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - scheme "k8s.io/client-go/kubernetes/scheme" - v1 "k8s.io/client-go/kubernetes/typed/core/v1" - record "k8s.io/client-go/tools/record" - kubeclient "knative.dev/pkg/client/injection/kube/client" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -const ( - defaultControllerAgentName = "cloudstoragesource-controller" - defaultFinalizerName = "cloudstoragesources.events.cloud.google.com" -) - -// NewImpl returns a controller.Impl that handles queuing and feeding work from -// the queue through an implementation of controller.Reconciler, delegating to -// the provided Interface and optional Finalizer methods. OptionsFn is used to return -// controller.Options to be used but the internal reconciler. -func NewImpl(ctx context.Context, r Interface, optionsFns ...controller.OptionsFn) *controller.Impl { - logger := logging.FromContext(ctx) - - // Check the options function input. It should be 0 or 1. - if len(optionsFns) > 1 { - logger.Fatalf("up to one options function is supported, found %d", len(optionsFns)) - } - - cloudstoragesourceInformer := cloudstoragesource.Get(ctx) - - lister := cloudstoragesourceInformer.Lister() - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client.Get(ctx), - Lister: lister, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - t := reflect.TypeOf(r).Elem() - queueName := fmt.Sprintf("%s.%s", strings.ReplaceAll(t.PkgPath(), "/", "-"), t.Name()) - - impl := controller.NewImpl(rec, logger, queueName) - agentName := defaultControllerAgentName - - // Pass impl to the options. Save any optional results. - for _, fn := range optionsFns { - opts := fn(impl) - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - if opts.AgentName != "" { - agentName = opts.AgentName - } - } - - rec.Recorder = createRecorder(ctx, agentName) - - return impl -} - -func createRecorder(ctx context.Context, agentName string) record.EventRecorder { - logger := logging.FromContext(ctx) - - recorder := controller.GetEventRecorder(ctx) - if recorder == nil { - // Create event broadcaster - logger.Debug("Creating event broadcaster") - eventBroadcaster := record.NewBroadcaster() - watches := []watch.Interface{ - eventBroadcaster.StartLogging(logger.Named("event-broadcaster").Infof), - eventBroadcaster.StartRecordingToSink( - &v1.EventSinkImpl{Interface: kubeclient.Get(ctx).CoreV1().Events("")}), - } - recorder = eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: agentName}) - go func() { - <-ctx.Done() - for _, w := range watches { - w.Stop() - } - }() - } - - return recorder -} - -func init() { - versionedscheme.AddToScheme(scheme.Scheme) -} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/reconciler.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/reconciler.go deleted file mode 100644 index c6d4e32292..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/reconciler.go +++ /dev/null @@ -1,434 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudstoragesource - -import ( - context "context" - json "encoding/json" - fmt "fmt" - reflect "reflect" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" - versioned "github.com/google/knative-gcp/pkg/client/clientset/versioned" - eventsv1alpha1 "github.com/google/knative-gcp/pkg/client/listers/events/v1alpha1" - zap "go.uber.org/zap" - v1 "k8s.io/api/core/v1" - equality "k8s.io/apimachinery/pkg/api/equality" - errors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - sets "k8s.io/apimachinery/pkg/util/sets" - cache "k8s.io/client-go/tools/cache" - record "k8s.io/client-go/tools/record" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -// Interface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.CloudStorageSource. -type Interface interface { - // ReconcileKind implements custom logic to reconcile v1alpha1.CloudStorageSource. Any changes - // to the objects .Status or .Finalizers will be propagated to the stored - // object. It is recommended that implementors do not call any update calls - // for the Kind inside of ReconcileKind, it is the responsibility of the calling - // controller to propagate those properties. The resource passed to ReconcileKind - // will always have an empty deletion timestamp. - ReconcileKind(ctx context.Context, o *v1alpha1.CloudStorageSource) reconciler.Event -} - -// Finalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.CloudStorageSource. -type Finalizer interface { - // FinalizeKind implements custom logic to finalize v1alpha1.CloudStorageSource. Any changes - // to the objects .Status or .Finalizers will be ignored. Returning a nil or - // Normal type reconciler.Event will allow the finalizer to be deleted on - // the resource. The resource passed to FinalizeKind will always have a set - // deletion timestamp. - FinalizeKind(ctx context.Context, o *v1alpha1.CloudStorageSource) reconciler.Event -} - -// ReadOnlyInterface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.CloudStorageSource if they want to process resources for which -// they are not the leader. -type ReadOnlyInterface interface { - // ObserveKind implements logic to observe v1alpha1.CloudStorageSource. - // This method should not write to the API. - ObserveKind(ctx context.Context, o *v1alpha1.CloudStorageSource) reconciler.Event -} - -// ReadOnlyFinalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.CloudStorageSource if they want to process tombstoned resources -// even when they are not the leader. Due to the nature of how finalizers are handled -// there are no guarantees that this will be called. -type ReadOnlyFinalizer interface { - // ObserveFinalizeKind implements custom logic to observe the final state of v1alpha1.CloudStorageSource. - // This method should not write to the API. - ObserveFinalizeKind(ctx context.Context, o *v1alpha1.CloudStorageSource) reconciler.Event -} - -// reconcilerImpl implements controller.Reconciler for v1alpha1.CloudStorageSource resources. -type reconcilerImpl struct { - // LeaderAwareFuncs is inlined to help us implement reconciler.LeaderAware - reconciler.LeaderAwareFuncs - - // Client is used to write back status updates. - Client versioned.Interface - - // Listers index properties about resources - Lister eventsv1alpha1.CloudStorageSourceLister - - // Recorder is an event recorder for recording Event resources to the - // Kubernetes API. - Recorder record.EventRecorder - - // configStore allows for decorating a context with config maps. - // +optional - configStore reconciler.ConfigStore - - // reconciler is the implementation of the business logic of the resource. - reconciler Interface - - // finalizerName is the name of the finalizer to reconcile. - finalizerName string -} - -// Check that our Reconciler implements controller.Reconciler -var _ controller.Reconciler = (*reconcilerImpl)(nil) - -// Check that our generated Reconciler is always LeaderAware. -var _ reconciler.LeaderAware = (*reconcilerImpl)(nil) - -func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versioned.Interface, lister eventsv1alpha1.CloudStorageSourceLister, recorder record.EventRecorder, r Interface, options ...controller.Options) controller.Reconciler { - // Check the options function input. It should be 0 or 1. - if len(options) > 1 { - logger.Fatalf("up to one options struct is supported, found %d", len(options)) - } - - // Fail fast when users inadvertently implement the other LeaderAware interface. - // For the typed reconcilers, Promote shouldn't take any arguments. - if _, ok := r.(reconciler.LeaderAware); ok { - logger.Fatalf("%T implements the incorrect LeaderAware interface. Promote() should not take an argument as genreconciler handles the enqueuing automatically.", r) - } - // TODO: Consider validating when folks implement ReadOnlyFinalizer, but not Finalizer. - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client, - Lister: lister, - Recorder: recorder, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - for _, opts := range options { - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - } - - return rec -} - -// Reconcile implements controller.Reconciler -func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { - logger := logging.FromContext(ctx) - - // Convert the namespace/name string into a distinct namespace and name - namespace, name, err := cache.SplitMetaNamespaceKey(key) - if err != nil { - logger.Errorf("invalid resource key: %s", key) - return nil - } - // Establish whether we are the leader for use below. - isLeader := r.IsLeaderFor(types.NamespacedName{ - Namespace: namespace, - Name: name, - }) - roi, isROI := r.reconciler.(ReadOnlyInterface) - rof, isROF := r.reconciler.(ReadOnlyFinalizer) - if !isLeader && !isROI && !isROF { - // If we are not the leader, and we don't implement either ReadOnly - // interface, then take a fast-path out. - return nil - } - - // If configStore is set, attach the frozen configuration to the context. - if r.configStore != nil { - ctx = r.configStore.ToContext(ctx) - } - - // Add the recorder to context. - ctx = controller.WithEventRecorder(ctx, r.Recorder) - - // Get the resource with this namespace/name. - - getter := r.Lister.CloudStorageSources(namespace) - - original, err := getter.Get(name) - - if errors.IsNotFound(err) { - // The resource may no longer exist, in which case we stop processing. - logger.Debugf("resource %q no longer exists", key) - return nil - } else if err != nil { - return err - } - - // Don't modify the informers copy. - resource := original.DeepCopy() - - var reconcileEvent reconciler.Event - if resource.GetDeletionTimestamp().IsZero() { - if isLeader { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ReconcileKind")) - - // Set and update the finalizer on resource if r.reconciler - // implements Finalizer. - if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil { - return fmt.Errorf("failed to set finalizers: %w", err) - } - - reconciler.PreProcessReconcile(ctx, resource) - - // Reconcile this copy of the resource and then write back any status - // updates regardless of whether the reconciliation errored out. - reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) - - reconciler.PostProcessReconcile(ctx, resource, original) - - } else if isROI { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveKind")) - - // Observe any changes to this resource, since we are not the leader. - reconcileEvent = roi.ObserveKind(ctx, resource) - } - } else if fin, ok := r.reconciler.(Finalizer); isLeader && ok { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "FinalizeKind")) - - // For finalizing reconcilers, if this resource being marked for deletion - // and reconciled cleanly (nil or normal event), remove the finalizer. - reconcileEvent = fin.FinalizeKind(ctx, resource) - if resource, err = r.clearFinalizer(ctx, resource, reconcileEvent); err != nil { - return fmt.Errorf("failed to clear finalizers: %w", err) - } - } else if !isLeader && isROF { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveFinalizeKind")) - - // For finalizing reconcilers, just observe when we aren't the leader. - reconcileEvent = rof.ObserveFinalizeKind(ctx, resource) - } - - // Synchronize the status. - if equality.Semantic.DeepEqual(original.Status, resource.Status) { - // If we didn't change anything then don't call updateStatus. - // This is important because the copy we loaded from the injectionInformer's - // cache may be stale and we don't want to overwrite a prior update - // to status with this stale state. - } else if !isLeader { - logger.Warn("Saw status changes when we aren't the leader!") - // TODO: Consider logging the diff at Debug? - } else if err = r.updateStatus(original, resource); err != nil { - logger.Warnw("Failed to update resource status", zap.Error(err)) - r.Recorder.Eventf(resource, v1.EventTypeWarning, "UpdateFailed", - "Failed to update status for %q: %v", resource.Name, err) - return err - } - - // Report the reconciler event, if any. - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - logger.Infow("Returned an event", zap.Any("event", reconcileEvent)) - r.Recorder.Eventf(resource, event.EventType, event.Reason, event.Format, event.Args...) - - // the event was wrapped inside an error, consider the reconciliation as failed - if _, isEvent := reconcileEvent.(*reconciler.ReconcilerEvent); !isEvent { - return reconcileEvent - } - return nil - } - - logger.Errorw("Returned an error", zap.Error(reconcileEvent)) - r.Recorder.Event(resource, v1.EventTypeWarning, "InternalError", reconcileEvent.Error()) - return reconcileEvent - } - - return nil -} - -func (r *reconcilerImpl) updateStatus(existing *v1alpha1.CloudStorageSource, desired *v1alpha1.CloudStorageSource) error { - existing = existing.DeepCopy() - return reconciler.RetryUpdateConflicts(func(attempts int) (err error) { - // The first iteration tries to use the injectionInformer's state, subsequent attempts fetch the latest state via API. - if attempts > 0 { - - getter := r.Client.EventsV1alpha1().CloudStorageSources(desired.Namespace) - - existing, err = getter.Get(desired.Name, metav1.GetOptions{}) - if err != nil { - return err - } - } - - // If there's nothing to update, just return. - if reflect.DeepEqual(existing.Status, desired.Status) { - return nil - } - - existing.Status = desired.Status - - updater := r.Client.EventsV1alpha1().CloudStorageSources(existing.Namespace) - - _, err = updater.UpdateStatus(existing) - return err - }) -} - -// updateFinalizersFiltered will update the Finalizers of the resource. -// TODO: this method could be generic and sync all finalizers. For now it only -// updates defaultFinalizerName or its override. -func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource *v1alpha1.CloudStorageSource) (*v1alpha1.CloudStorageSource, error) { - - getter := r.Lister.CloudStorageSources(resource.Namespace) - - actual, err := getter.Get(resource.Name) - if err != nil { - return resource, err - } - - // Don't modify the informers copy. - existing := actual.DeepCopy() - - var finalizers []string - - // If there's nothing to update, just return. - existingFinalizers := sets.NewString(existing.Finalizers...) - desiredFinalizers := sets.NewString(resource.Finalizers...) - - if desiredFinalizers.Has(r.finalizerName) { - if existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Add the finalizer. - finalizers = append(existing.Finalizers, r.finalizerName) - } else { - if !existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Remove the finalizer. - existingFinalizers.Delete(r.finalizerName) - finalizers = existingFinalizers.List() - } - - mergePatch := map[string]interface{}{ - "metadata": map[string]interface{}{ - "finalizers": finalizers, - "resourceVersion": existing.ResourceVersion, - }, - } - - patch, err := json.Marshal(mergePatch) - if err != nil { - return resource, err - } - - patcher := r.Client.EventsV1alpha1().CloudStorageSources(resource.Namespace) - - resourceName := resource.Name - resource, err = patcher.Patch(resourceName, types.MergePatchType, patch) - if err != nil { - r.Recorder.Eventf(resource, v1.EventTypeWarning, "FinalizerUpdateFailed", - "Failed to update finalizers for %q: %v", resourceName, err) - } else { - r.Recorder.Eventf(resource, v1.EventTypeNormal, "FinalizerUpdate", - "Updated %q finalizers", resource.GetName()) - } - return resource, err -} - -func (r *reconcilerImpl) setFinalizerIfFinalizer(ctx context.Context, resource *v1alpha1.CloudStorageSource) (*v1alpha1.CloudStorageSource, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - // If this resource is not being deleted, mark the finalizer. - if resource.GetDeletionTimestamp().IsZero() { - finalizers.Insert(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} - -func (r *reconcilerImpl) clearFinalizer(ctx context.Context, resource *v1alpha1.CloudStorageSource, reconcileEvent reconciler.Event) (*v1alpha1.CloudStorageSource, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - if resource.GetDeletionTimestamp().IsZero() { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - if event.EventType == v1.EventTypeNormal { - finalizers.Delete(r.finalizerName) - } - } - } else { - finalizers.Delete(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/stub/controller.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/stub/controller.go deleted file mode 100644 index 37b5c223b9..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/stub/controller.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudstoragesource - -import ( - context "context" - - cloudstoragesource "github.com/google/knative-gcp/pkg/client/injection/informers/events/v1alpha1/cloudstoragesource" - v1alpha1cloudstoragesource "github.com/google/knative-gcp/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource" - configmap "knative.dev/pkg/configmap" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// NewController creates a Reconciler for CloudStorageSource and returns the result of NewImpl. -func NewController( - ctx context.Context, - cmw configmap.Watcher, -) *controller.Impl { - logger := logging.FromContext(ctx) - - cloudstoragesourceInformer := cloudstoragesource.Get(ctx) - - // TODO: setup additional informers here. - - r := &Reconciler{} - impl := v1alpha1cloudstoragesource.NewImpl(ctx, r) - - logger.Info("Setting up event handlers.") - - cloudstoragesourceInformer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue)) - - // TODO: add additional informer event handlers here. - - return impl -} diff --git a/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/stub/reconciler.go b/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/stub/reconciler.go deleted file mode 100644 index cb0bb44fda..0000000000 --- a/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource/stub/reconciler.go +++ /dev/null @@ -1,87 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package cloudstoragesource - -import ( - context "context" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/events/v1alpha1" - cloudstoragesource "github.com/google/knative-gcp/pkg/client/injection/reconciler/events/v1alpha1/cloudstoragesource" - v1 "k8s.io/api/core/v1" - reconciler "knative.dev/pkg/reconciler" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// newReconciledNormal makes a new reconciler event with event type Normal, and -// reason CloudStorageSourceReconciled. -func newReconciledNormal(namespace, name string) reconciler.Event { - return reconciler.NewEvent(v1.EventTypeNormal, "CloudStorageSourceReconciled", "CloudStorageSource reconciled: \"%s/%s\"", namespace, name) -} - -// Reconciler implements controller.Reconciler for CloudStorageSource resources. -type Reconciler struct { - // TODO: add additional requirements here. -} - -// Check that our Reconciler implements Interface -var _ cloudstoragesource.Interface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements Finalizer -//var _ cloudstoragesource.Finalizer = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyInterface -// Implement this to observe resources even when we are not the leader. -//var _ cloudstoragesource.ReadOnlyInterface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyFinalizer -// Implement this to observe tombstoned resources even when we are not -// the leader (best effort). -//var _ cloudstoragesource.ReadOnlyFinalizer = (*Reconciler)(nil) - -// ReconcileKind implements Interface.ReconcileKind. -func (r *Reconciler) ReconcileKind(ctx context.Context, o *v1alpha1.CloudStorageSource) reconciler.Event { - // TODO: use this if the resource implements InitializeConditions. - // o.Status.InitializeConditions() - - // TODO: add custom reconciliation logic here. - - // TODO: use this if the object has .status.ObservedGeneration. - // o.Status.ObservedGeneration = o.Generation - return newReconciledNormal(o.Namespace, o.Name) -} - -// Optionally, use FinalizeKind to add finalizers. FinalizeKind will be called -// when the resource is deleted. -//func (r *Reconciler) FinalizeKind(ctx context.Context, o *v1alpha1.CloudStorageSource) reconciler.Event { -// // TODO: add custom finalization logic here. -// return nil -//} - -// Optionally, use ObserveKind to observe the resource when we are not the leader. -// func (r *Reconciler) ObserveKind(ctx context.Context, o *v1alpha1.CloudStorageSource) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -// } - -// Optionally, use ObserveFinalizeKind to observe resources being finalized when we are no the leader. -//func (r *Reconciler) ObserveFinalizeKind(ctx context.Context, o *v1alpha1.CloudStorageSource) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -//} diff --git a/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/controller.go b/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/controller.go deleted file mode 100644 index 94e941440c..0000000000 --- a/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/controller.go +++ /dev/null @@ -1,139 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package pullsubscription - -import ( - context "context" - fmt "fmt" - reflect "reflect" - strings "strings" - - versionedscheme "github.com/google/knative-gcp/pkg/client/clientset/versioned/scheme" - client "github.com/google/knative-gcp/pkg/client/injection/client" - pullsubscription "github.com/google/knative-gcp/pkg/client/injection/informers/intevents/v1alpha1/pullsubscription" - corev1 "k8s.io/api/core/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - scheme "k8s.io/client-go/kubernetes/scheme" - v1 "k8s.io/client-go/kubernetes/typed/core/v1" - record "k8s.io/client-go/tools/record" - kubeclient "knative.dev/pkg/client/injection/kube/client" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -const ( - defaultControllerAgentName = "pullsubscription-controller" - defaultFinalizerName = "pullsubscriptions.internal.events.cloud.google.com" -) - -// NewImpl returns a controller.Impl that handles queuing and feeding work from -// the queue through an implementation of controller.Reconciler, delegating to -// the provided Interface and optional Finalizer methods. OptionsFn is used to return -// controller.Options to be used but the internal reconciler. -func NewImpl(ctx context.Context, r Interface, optionsFns ...controller.OptionsFn) *controller.Impl { - logger := logging.FromContext(ctx) - - // Check the options function input. It should be 0 or 1. - if len(optionsFns) > 1 { - logger.Fatalf("up to one options function is supported, found %d", len(optionsFns)) - } - - pullsubscriptionInformer := pullsubscription.Get(ctx) - - lister := pullsubscriptionInformer.Lister() - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client.Get(ctx), - Lister: lister, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - t := reflect.TypeOf(r).Elem() - queueName := fmt.Sprintf("%s.%s", strings.ReplaceAll(t.PkgPath(), "/", "-"), t.Name()) - - impl := controller.NewImpl(rec, logger, queueName) - agentName := defaultControllerAgentName - - // Pass impl to the options. Save any optional results. - for _, fn := range optionsFns { - opts := fn(impl) - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - if opts.AgentName != "" { - agentName = opts.AgentName - } - } - - rec.Recorder = createRecorder(ctx, agentName) - - return impl -} - -func createRecorder(ctx context.Context, agentName string) record.EventRecorder { - logger := logging.FromContext(ctx) - - recorder := controller.GetEventRecorder(ctx) - if recorder == nil { - // Create event broadcaster - logger.Debug("Creating event broadcaster") - eventBroadcaster := record.NewBroadcaster() - watches := []watch.Interface{ - eventBroadcaster.StartLogging(logger.Named("event-broadcaster").Infof), - eventBroadcaster.StartRecordingToSink( - &v1.EventSinkImpl{Interface: kubeclient.Get(ctx).CoreV1().Events("")}), - } - recorder = eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: agentName}) - go func() { - <-ctx.Done() - for _, w := range watches { - w.Stop() - } - }() - } - - return recorder -} - -func init() { - versionedscheme.AddToScheme(scheme.Scheme) -} diff --git a/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/reconciler.go b/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/reconciler.go deleted file mode 100644 index 99de60781c..0000000000 --- a/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/reconciler.go +++ /dev/null @@ -1,434 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package pullsubscription - -import ( - context "context" - json "encoding/json" - fmt "fmt" - reflect "reflect" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" - versioned "github.com/google/knative-gcp/pkg/client/clientset/versioned" - inteventsv1alpha1 "github.com/google/knative-gcp/pkg/client/listers/intevents/v1alpha1" - zap "go.uber.org/zap" - v1 "k8s.io/api/core/v1" - equality "k8s.io/apimachinery/pkg/api/equality" - errors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - sets "k8s.io/apimachinery/pkg/util/sets" - cache "k8s.io/client-go/tools/cache" - record "k8s.io/client-go/tools/record" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -// Interface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.PullSubscription. -type Interface interface { - // ReconcileKind implements custom logic to reconcile v1alpha1.PullSubscription. Any changes - // to the objects .Status or .Finalizers will be propagated to the stored - // object. It is recommended that implementors do not call any update calls - // for the Kind inside of ReconcileKind, it is the responsibility of the calling - // controller to propagate those properties. The resource passed to ReconcileKind - // will always have an empty deletion timestamp. - ReconcileKind(ctx context.Context, o *v1alpha1.PullSubscription) reconciler.Event -} - -// Finalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.PullSubscription. -type Finalizer interface { - // FinalizeKind implements custom logic to finalize v1alpha1.PullSubscription. Any changes - // to the objects .Status or .Finalizers will be ignored. Returning a nil or - // Normal type reconciler.Event will allow the finalizer to be deleted on - // the resource. The resource passed to FinalizeKind will always have a set - // deletion timestamp. - FinalizeKind(ctx context.Context, o *v1alpha1.PullSubscription) reconciler.Event -} - -// ReadOnlyInterface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.PullSubscription if they want to process resources for which -// they are not the leader. -type ReadOnlyInterface interface { - // ObserveKind implements logic to observe v1alpha1.PullSubscription. - // This method should not write to the API. - ObserveKind(ctx context.Context, o *v1alpha1.PullSubscription) reconciler.Event -} - -// ReadOnlyFinalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.PullSubscription if they want to process tombstoned resources -// even when they are not the leader. Due to the nature of how finalizers are handled -// there are no guarantees that this will be called. -type ReadOnlyFinalizer interface { - // ObserveFinalizeKind implements custom logic to observe the final state of v1alpha1.PullSubscription. - // This method should not write to the API. - ObserveFinalizeKind(ctx context.Context, o *v1alpha1.PullSubscription) reconciler.Event -} - -// reconcilerImpl implements controller.Reconciler for v1alpha1.PullSubscription resources. -type reconcilerImpl struct { - // LeaderAwareFuncs is inlined to help us implement reconciler.LeaderAware - reconciler.LeaderAwareFuncs - - // Client is used to write back status updates. - Client versioned.Interface - - // Listers index properties about resources - Lister inteventsv1alpha1.PullSubscriptionLister - - // Recorder is an event recorder for recording Event resources to the - // Kubernetes API. - Recorder record.EventRecorder - - // configStore allows for decorating a context with config maps. - // +optional - configStore reconciler.ConfigStore - - // reconciler is the implementation of the business logic of the resource. - reconciler Interface - - // finalizerName is the name of the finalizer to reconcile. - finalizerName string -} - -// Check that our Reconciler implements controller.Reconciler -var _ controller.Reconciler = (*reconcilerImpl)(nil) - -// Check that our generated Reconciler is always LeaderAware. -var _ reconciler.LeaderAware = (*reconcilerImpl)(nil) - -func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versioned.Interface, lister inteventsv1alpha1.PullSubscriptionLister, recorder record.EventRecorder, r Interface, options ...controller.Options) controller.Reconciler { - // Check the options function input. It should be 0 or 1. - if len(options) > 1 { - logger.Fatalf("up to one options struct is supported, found %d", len(options)) - } - - // Fail fast when users inadvertently implement the other LeaderAware interface. - // For the typed reconcilers, Promote shouldn't take any arguments. - if _, ok := r.(reconciler.LeaderAware); ok { - logger.Fatalf("%T implements the incorrect LeaderAware interface. Promote() should not take an argument as genreconciler handles the enqueuing automatically.", r) - } - // TODO: Consider validating when folks implement ReadOnlyFinalizer, but not Finalizer. - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client, - Lister: lister, - Recorder: recorder, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - for _, opts := range options { - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - } - - return rec -} - -// Reconcile implements controller.Reconciler -func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { - logger := logging.FromContext(ctx) - - // Convert the namespace/name string into a distinct namespace and name - namespace, name, err := cache.SplitMetaNamespaceKey(key) - if err != nil { - logger.Errorf("invalid resource key: %s", key) - return nil - } - // Establish whether we are the leader for use below. - isLeader := r.IsLeaderFor(types.NamespacedName{ - Namespace: namespace, - Name: name, - }) - roi, isROI := r.reconciler.(ReadOnlyInterface) - rof, isROF := r.reconciler.(ReadOnlyFinalizer) - if !isLeader && !isROI && !isROF { - // If we are not the leader, and we don't implement either ReadOnly - // interface, then take a fast-path out. - return nil - } - - // If configStore is set, attach the frozen configuration to the context. - if r.configStore != nil { - ctx = r.configStore.ToContext(ctx) - } - - // Add the recorder to context. - ctx = controller.WithEventRecorder(ctx, r.Recorder) - - // Get the resource with this namespace/name. - - getter := r.Lister.PullSubscriptions(namespace) - - original, err := getter.Get(name) - - if errors.IsNotFound(err) { - // The resource may no longer exist, in which case we stop processing. - logger.Debugf("resource %q no longer exists", key) - return nil - } else if err != nil { - return err - } - - // Don't modify the informers copy. - resource := original.DeepCopy() - - var reconcileEvent reconciler.Event - if resource.GetDeletionTimestamp().IsZero() { - if isLeader { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ReconcileKind")) - - // Set and update the finalizer on resource if r.reconciler - // implements Finalizer. - if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil { - return fmt.Errorf("failed to set finalizers: %w", err) - } - - reconciler.PreProcessReconcile(ctx, resource) - - // Reconcile this copy of the resource and then write back any status - // updates regardless of whether the reconciliation errored out. - reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) - - reconciler.PostProcessReconcile(ctx, resource, original) - - } else if isROI { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveKind")) - - // Observe any changes to this resource, since we are not the leader. - reconcileEvent = roi.ObserveKind(ctx, resource) - } - } else if fin, ok := r.reconciler.(Finalizer); isLeader && ok { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "FinalizeKind")) - - // For finalizing reconcilers, if this resource being marked for deletion - // and reconciled cleanly (nil or normal event), remove the finalizer. - reconcileEvent = fin.FinalizeKind(ctx, resource) - if resource, err = r.clearFinalizer(ctx, resource, reconcileEvent); err != nil { - return fmt.Errorf("failed to clear finalizers: %w", err) - } - } else if !isLeader && isROF { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveFinalizeKind")) - - // For finalizing reconcilers, just observe when we aren't the leader. - reconcileEvent = rof.ObserveFinalizeKind(ctx, resource) - } - - // Synchronize the status. - if equality.Semantic.DeepEqual(original.Status, resource.Status) { - // If we didn't change anything then don't call updateStatus. - // This is important because the copy we loaded from the injectionInformer's - // cache may be stale and we don't want to overwrite a prior update - // to status with this stale state. - } else if !isLeader { - logger.Warn("Saw status changes when we aren't the leader!") - // TODO: Consider logging the diff at Debug? - } else if err = r.updateStatus(original, resource); err != nil { - logger.Warnw("Failed to update resource status", zap.Error(err)) - r.Recorder.Eventf(resource, v1.EventTypeWarning, "UpdateFailed", - "Failed to update status for %q: %v", resource.Name, err) - return err - } - - // Report the reconciler event, if any. - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - logger.Infow("Returned an event", zap.Any("event", reconcileEvent)) - r.Recorder.Eventf(resource, event.EventType, event.Reason, event.Format, event.Args...) - - // the event was wrapped inside an error, consider the reconciliation as failed - if _, isEvent := reconcileEvent.(*reconciler.ReconcilerEvent); !isEvent { - return reconcileEvent - } - return nil - } - - logger.Errorw("Returned an error", zap.Error(reconcileEvent)) - r.Recorder.Event(resource, v1.EventTypeWarning, "InternalError", reconcileEvent.Error()) - return reconcileEvent - } - - return nil -} - -func (r *reconcilerImpl) updateStatus(existing *v1alpha1.PullSubscription, desired *v1alpha1.PullSubscription) error { - existing = existing.DeepCopy() - return reconciler.RetryUpdateConflicts(func(attempts int) (err error) { - // The first iteration tries to use the injectionInformer's state, subsequent attempts fetch the latest state via API. - if attempts > 0 { - - getter := r.Client.InternalV1alpha1().PullSubscriptions(desired.Namespace) - - existing, err = getter.Get(desired.Name, metav1.GetOptions{}) - if err != nil { - return err - } - } - - // If there's nothing to update, just return. - if reflect.DeepEqual(existing.Status, desired.Status) { - return nil - } - - existing.Status = desired.Status - - updater := r.Client.InternalV1alpha1().PullSubscriptions(existing.Namespace) - - _, err = updater.UpdateStatus(existing) - return err - }) -} - -// updateFinalizersFiltered will update the Finalizers of the resource. -// TODO: this method could be generic and sync all finalizers. For now it only -// updates defaultFinalizerName or its override. -func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource *v1alpha1.PullSubscription) (*v1alpha1.PullSubscription, error) { - - getter := r.Lister.PullSubscriptions(resource.Namespace) - - actual, err := getter.Get(resource.Name) - if err != nil { - return resource, err - } - - // Don't modify the informers copy. - existing := actual.DeepCopy() - - var finalizers []string - - // If there's nothing to update, just return. - existingFinalizers := sets.NewString(existing.Finalizers...) - desiredFinalizers := sets.NewString(resource.Finalizers...) - - if desiredFinalizers.Has(r.finalizerName) { - if existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Add the finalizer. - finalizers = append(existing.Finalizers, r.finalizerName) - } else { - if !existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Remove the finalizer. - existingFinalizers.Delete(r.finalizerName) - finalizers = existingFinalizers.List() - } - - mergePatch := map[string]interface{}{ - "metadata": map[string]interface{}{ - "finalizers": finalizers, - "resourceVersion": existing.ResourceVersion, - }, - } - - patch, err := json.Marshal(mergePatch) - if err != nil { - return resource, err - } - - patcher := r.Client.InternalV1alpha1().PullSubscriptions(resource.Namespace) - - resourceName := resource.Name - resource, err = patcher.Patch(resourceName, types.MergePatchType, patch) - if err != nil { - r.Recorder.Eventf(resource, v1.EventTypeWarning, "FinalizerUpdateFailed", - "Failed to update finalizers for %q: %v", resourceName, err) - } else { - r.Recorder.Eventf(resource, v1.EventTypeNormal, "FinalizerUpdate", - "Updated %q finalizers", resource.GetName()) - } - return resource, err -} - -func (r *reconcilerImpl) setFinalizerIfFinalizer(ctx context.Context, resource *v1alpha1.PullSubscription) (*v1alpha1.PullSubscription, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - // If this resource is not being deleted, mark the finalizer. - if resource.GetDeletionTimestamp().IsZero() { - finalizers.Insert(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} - -func (r *reconcilerImpl) clearFinalizer(ctx context.Context, resource *v1alpha1.PullSubscription, reconcileEvent reconciler.Event) (*v1alpha1.PullSubscription, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - if resource.GetDeletionTimestamp().IsZero() { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - if event.EventType == v1.EventTypeNormal { - finalizers.Delete(r.finalizerName) - } - } - } else { - finalizers.Delete(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} diff --git a/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/stub/controller.go b/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/stub/controller.go deleted file mode 100644 index 4e3c8b1724..0000000000 --- a/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/stub/controller.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package pullsubscription - -import ( - context "context" - - pullsubscription "github.com/google/knative-gcp/pkg/client/injection/informers/intevents/v1alpha1/pullsubscription" - v1alpha1pullsubscription "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription" - configmap "knative.dev/pkg/configmap" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// NewController creates a Reconciler for PullSubscription and returns the result of NewImpl. -func NewController( - ctx context.Context, - cmw configmap.Watcher, -) *controller.Impl { - logger := logging.FromContext(ctx) - - pullsubscriptionInformer := pullsubscription.Get(ctx) - - // TODO: setup additional informers here. - - r := &Reconciler{} - impl := v1alpha1pullsubscription.NewImpl(ctx, r) - - logger.Info("Setting up event handlers.") - - pullsubscriptionInformer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue)) - - // TODO: add additional informer event handlers here. - - return impl -} diff --git a/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/stub/reconciler.go b/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/stub/reconciler.go deleted file mode 100644 index c1b6c82a61..0000000000 --- a/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription/stub/reconciler.go +++ /dev/null @@ -1,87 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package pullsubscription - -import ( - context "context" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" - pullsubscription "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/pullsubscription" - v1 "k8s.io/api/core/v1" - reconciler "knative.dev/pkg/reconciler" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// newReconciledNormal makes a new reconciler event with event type Normal, and -// reason PullSubscriptionReconciled. -func newReconciledNormal(namespace, name string) reconciler.Event { - return reconciler.NewEvent(v1.EventTypeNormal, "PullSubscriptionReconciled", "PullSubscription reconciled: \"%s/%s\"", namespace, name) -} - -// Reconciler implements controller.Reconciler for PullSubscription resources. -type Reconciler struct { - // TODO: add additional requirements here. -} - -// Check that our Reconciler implements Interface -var _ pullsubscription.Interface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements Finalizer -//var _ pullsubscription.Finalizer = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyInterface -// Implement this to observe resources even when we are not the leader. -//var _ pullsubscription.ReadOnlyInterface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyFinalizer -// Implement this to observe tombstoned resources even when we are not -// the leader (best effort). -//var _ pullsubscription.ReadOnlyFinalizer = (*Reconciler)(nil) - -// ReconcileKind implements Interface.ReconcileKind. -func (r *Reconciler) ReconcileKind(ctx context.Context, o *v1alpha1.PullSubscription) reconciler.Event { - // TODO: use this if the resource implements InitializeConditions. - // o.Status.InitializeConditions() - - // TODO: add custom reconciliation logic here. - - // TODO: use this if the object has .status.ObservedGeneration. - // o.Status.ObservedGeneration = o.Generation - return newReconciledNormal(o.Namespace, o.Name) -} - -// Optionally, use FinalizeKind to add finalizers. FinalizeKind will be called -// when the resource is deleted. -//func (r *Reconciler) FinalizeKind(ctx context.Context, o *v1alpha1.PullSubscription) reconciler.Event { -// // TODO: add custom finalization logic here. -// return nil -//} - -// Optionally, use ObserveKind to observe the resource when we are not the leader. -// func (r *Reconciler) ObserveKind(ctx context.Context, o *v1alpha1.PullSubscription) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -// } - -// Optionally, use ObserveFinalizeKind to observe resources being finalized when we are no the leader. -//func (r *Reconciler) ObserveFinalizeKind(ctx context.Context, o *v1alpha1.PullSubscription) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -//} diff --git a/pkg/client/injection/reconciler/intevents/v1alpha1/topic/controller.go b/pkg/client/injection/reconciler/intevents/v1alpha1/topic/controller.go deleted file mode 100644 index 73f252b0c0..0000000000 --- a/pkg/client/injection/reconciler/intevents/v1alpha1/topic/controller.go +++ /dev/null @@ -1,139 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package topic - -import ( - context "context" - fmt "fmt" - reflect "reflect" - strings "strings" - - versionedscheme "github.com/google/knative-gcp/pkg/client/clientset/versioned/scheme" - client "github.com/google/knative-gcp/pkg/client/injection/client" - topic "github.com/google/knative-gcp/pkg/client/injection/informers/intevents/v1alpha1/topic" - corev1 "k8s.io/api/core/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - scheme "k8s.io/client-go/kubernetes/scheme" - v1 "k8s.io/client-go/kubernetes/typed/core/v1" - record "k8s.io/client-go/tools/record" - kubeclient "knative.dev/pkg/client/injection/kube/client" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -const ( - defaultControllerAgentName = "topic-controller" - defaultFinalizerName = "topics.internal.events.cloud.google.com" -) - -// NewImpl returns a controller.Impl that handles queuing and feeding work from -// the queue through an implementation of controller.Reconciler, delegating to -// the provided Interface and optional Finalizer methods. OptionsFn is used to return -// controller.Options to be used but the internal reconciler. -func NewImpl(ctx context.Context, r Interface, optionsFns ...controller.OptionsFn) *controller.Impl { - logger := logging.FromContext(ctx) - - // Check the options function input. It should be 0 or 1. - if len(optionsFns) > 1 { - logger.Fatalf("up to one options function is supported, found %d", len(optionsFns)) - } - - topicInformer := topic.Get(ctx) - - lister := topicInformer.Lister() - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client.Get(ctx), - Lister: lister, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - t := reflect.TypeOf(r).Elem() - queueName := fmt.Sprintf("%s.%s", strings.ReplaceAll(t.PkgPath(), "/", "-"), t.Name()) - - impl := controller.NewImpl(rec, logger, queueName) - agentName := defaultControllerAgentName - - // Pass impl to the options. Save any optional results. - for _, fn := range optionsFns { - opts := fn(impl) - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - if opts.AgentName != "" { - agentName = opts.AgentName - } - } - - rec.Recorder = createRecorder(ctx, agentName) - - return impl -} - -func createRecorder(ctx context.Context, agentName string) record.EventRecorder { - logger := logging.FromContext(ctx) - - recorder := controller.GetEventRecorder(ctx) - if recorder == nil { - // Create event broadcaster - logger.Debug("Creating event broadcaster") - eventBroadcaster := record.NewBroadcaster() - watches := []watch.Interface{ - eventBroadcaster.StartLogging(logger.Named("event-broadcaster").Infof), - eventBroadcaster.StartRecordingToSink( - &v1.EventSinkImpl{Interface: kubeclient.Get(ctx).CoreV1().Events("")}), - } - recorder = eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: agentName}) - go func() { - <-ctx.Done() - for _, w := range watches { - w.Stop() - } - }() - } - - return recorder -} - -func init() { - versionedscheme.AddToScheme(scheme.Scheme) -} diff --git a/pkg/client/injection/reconciler/intevents/v1alpha1/topic/reconciler.go b/pkg/client/injection/reconciler/intevents/v1alpha1/topic/reconciler.go deleted file mode 100644 index ffd903bd40..0000000000 --- a/pkg/client/injection/reconciler/intevents/v1alpha1/topic/reconciler.go +++ /dev/null @@ -1,434 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package topic - -import ( - context "context" - json "encoding/json" - fmt "fmt" - reflect "reflect" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" - versioned "github.com/google/knative-gcp/pkg/client/clientset/versioned" - inteventsv1alpha1 "github.com/google/knative-gcp/pkg/client/listers/intevents/v1alpha1" - zap "go.uber.org/zap" - v1 "k8s.io/api/core/v1" - equality "k8s.io/apimachinery/pkg/api/equality" - errors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - sets "k8s.io/apimachinery/pkg/util/sets" - cache "k8s.io/client-go/tools/cache" - record "k8s.io/client-go/tools/record" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -// Interface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.Topic. -type Interface interface { - // ReconcileKind implements custom logic to reconcile v1alpha1.Topic. Any changes - // to the objects .Status or .Finalizers will be propagated to the stored - // object. It is recommended that implementors do not call any update calls - // for the Kind inside of ReconcileKind, it is the responsibility of the calling - // controller to propagate those properties. The resource passed to ReconcileKind - // will always have an empty deletion timestamp. - ReconcileKind(ctx context.Context, o *v1alpha1.Topic) reconciler.Event -} - -// Finalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.Topic. -type Finalizer interface { - // FinalizeKind implements custom logic to finalize v1alpha1.Topic. Any changes - // to the objects .Status or .Finalizers will be ignored. Returning a nil or - // Normal type reconciler.Event will allow the finalizer to be deleted on - // the resource. The resource passed to FinalizeKind will always have a set - // deletion timestamp. - FinalizeKind(ctx context.Context, o *v1alpha1.Topic) reconciler.Event -} - -// ReadOnlyInterface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.Topic if they want to process resources for which -// they are not the leader. -type ReadOnlyInterface interface { - // ObserveKind implements logic to observe v1alpha1.Topic. - // This method should not write to the API. - ObserveKind(ctx context.Context, o *v1alpha1.Topic) reconciler.Event -} - -// ReadOnlyFinalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.Topic if they want to process tombstoned resources -// even when they are not the leader. Due to the nature of how finalizers are handled -// there are no guarantees that this will be called. -type ReadOnlyFinalizer interface { - // ObserveFinalizeKind implements custom logic to observe the final state of v1alpha1.Topic. - // This method should not write to the API. - ObserveFinalizeKind(ctx context.Context, o *v1alpha1.Topic) reconciler.Event -} - -// reconcilerImpl implements controller.Reconciler for v1alpha1.Topic resources. -type reconcilerImpl struct { - // LeaderAwareFuncs is inlined to help us implement reconciler.LeaderAware - reconciler.LeaderAwareFuncs - - // Client is used to write back status updates. - Client versioned.Interface - - // Listers index properties about resources - Lister inteventsv1alpha1.TopicLister - - // Recorder is an event recorder for recording Event resources to the - // Kubernetes API. - Recorder record.EventRecorder - - // configStore allows for decorating a context with config maps. - // +optional - configStore reconciler.ConfigStore - - // reconciler is the implementation of the business logic of the resource. - reconciler Interface - - // finalizerName is the name of the finalizer to reconcile. - finalizerName string -} - -// Check that our Reconciler implements controller.Reconciler -var _ controller.Reconciler = (*reconcilerImpl)(nil) - -// Check that our generated Reconciler is always LeaderAware. -var _ reconciler.LeaderAware = (*reconcilerImpl)(nil) - -func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versioned.Interface, lister inteventsv1alpha1.TopicLister, recorder record.EventRecorder, r Interface, options ...controller.Options) controller.Reconciler { - // Check the options function input. It should be 0 or 1. - if len(options) > 1 { - logger.Fatalf("up to one options struct is supported, found %d", len(options)) - } - - // Fail fast when users inadvertently implement the other LeaderAware interface. - // For the typed reconcilers, Promote shouldn't take any arguments. - if _, ok := r.(reconciler.LeaderAware); ok { - logger.Fatalf("%T implements the incorrect LeaderAware interface. Promote() should not take an argument as genreconciler handles the enqueuing automatically.", r) - } - // TODO: Consider validating when folks implement ReadOnlyFinalizer, but not Finalizer. - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client, - Lister: lister, - Recorder: recorder, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - for _, opts := range options { - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - } - - return rec -} - -// Reconcile implements controller.Reconciler -func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { - logger := logging.FromContext(ctx) - - // Convert the namespace/name string into a distinct namespace and name - namespace, name, err := cache.SplitMetaNamespaceKey(key) - if err != nil { - logger.Errorf("invalid resource key: %s", key) - return nil - } - // Establish whether we are the leader for use below. - isLeader := r.IsLeaderFor(types.NamespacedName{ - Namespace: namespace, - Name: name, - }) - roi, isROI := r.reconciler.(ReadOnlyInterface) - rof, isROF := r.reconciler.(ReadOnlyFinalizer) - if !isLeader && !isROI && !isROF { - // If we are not the leader, and we don't implement either ReadOnly - // interface, then take a fast-path out. - return nil - } - - // If configStore is set, attach the frozen configuration to the context. - if r.configStore != nil { - ctx = r.configStore.ToContext(ctx) - } - - // Add the recorder to context. - ctx = controller.WithEventRecorder(ctx, r.Recorder) - - // Get the resource with this namespace/name. - - getter := r.Lister.Topics(namespace) - - original, err := getter.Get(name) - - if errors.IsNotFound(err) { - // The resource may no longer exist, in which case we stop processing. - logger.Debugf("resource %q no longer exists", key) - return nil - } else if err != nil { - return err - } - - // Don't modify the informers copy. - resource := original.DeepCopy() - - var reconcileEvent reconciler.Event - if resource.GetDeletionTimestamp().IsZero() { - if isLeader { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ReconcileKind")) - - // Set and update the finalizer on resource if r.reconciler - // implements Finalizer. - if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil { - return fmt.Errorf("failed to set finalizers: %w", err) - } - - reconciler.PreProcessReconcile(ctx, resource) - - // Reconcile this copy of the resource and then write back any status - // updates regardless of whether the reconciliation errored out. - reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) - - reconciler.PostProcessReconcile(ctx, resource, original) - - } else if isROI { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveKind")) - - // Observe any changes to this resource, since we are not the leader. - reconcileEvent = roi.ObserveKind(ctx, resource) - } - } else if fin, ok := r.reconciler.(Finalizer); isLeader && ok { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "FinalizeKind")) - - // For finalizing reconcilers, if this resource being marked for deletion - // and reconciled cleanly (nil or normal event), remove the finalizer. - reconcileEvent = fin.FinalizeKind(ctx, resource) - if resource, err = r.clearFinalizer(ctx, resource, reconcileEvent); err != nil { - return fmt.Errorf("failed to clear finalizers: %w", err) - } - } else if !isLeader && isROF { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveFinalizeKind")) - - // For finalizing reconcilers, just observe when we aren't the leader. - reconcileEvent = rof.ObserveFinalizeKind(ctx, resource) - } - - // Synchronize the status. - if equality.Semantic.DeepEqual(original.Status, resource.Status) { - // If we didn't change anything then don't call updateStatus. - // This is important because the copy we loaded from the injectionInformer's - // cache may be stale and we don't want to overwrite a prior update - // to status with this stale state. - } else if !isLeader { - logger.Warn("Saw status changes when we aren't the leader!") - // TODO: Consider logging the diff at Debug? - } else if err = r.updateStatus(original, resource); err != nil { - logger.Warnw("Failed to update resource status", zap.Error(err)) - r.Recorder.Eventf(resource, v1.EventTypeWarning, "UpdateFailed", - "Failed to update status for %q: %v", resource.Name, err) - return err - } - - // Report the reconciler event, if any. - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - logger.Infow("Returned an event", zap.Any("event", reconcileEvent)) - r.Recorder.Eventf(resource, event.EventType, event.Reason, event.Format, event.Args...) - - // the event was wrapped inside an error, consider the reconciliation as failed - if _, isEvent := reconcileEvent.(*reconciler.ReconcilerEvent); !isEvent { - return reconcileEvent - } - return nil - } - - logger.Errorw("Returned an error", zap.Error(reconcileEvent)) - r.Recorder.Event(resource, v1.EventTypeWarning, "InternalError", reconcileEvent.Error()) - return reconcileEvent - } - - return nil -} - -func (r *reconcilerImpl) updateStatus(existing *v1alpha1.Topic, desired *v1alpha1.Topic) error { - existing = existing.DeepCopy() - return reconciler.RetryUpdateConflicts(func(attempts int) (err error) { - // The first iteration tries to use the injectionInformer's state, subsequent attempts fetch the latest state via API. - if attempts > 0 { - - getter := r.Client.InternalV1alpha1().Topics(desired.Namespace) - - existing, err = getter.Get(desired.Name, metav1.GetOptions{}) - if err != nil { - return err - } - } - - // If there's nothing to update, just return. - if reflect.DeepEqual(existing.Status, desired.Status) { - return nil - } - - existing.Status = desired.Status - - updater := r.Client.InternalV1alpha1().Topics(existing.Namespace) - - _, err = updater.UpdateStatus(existing) - return err - }) -} - -// updateFinalizersFiltered will update the Finalizers of the resource. -// TODO: this method could be generic and sync all finalizers. For now it only -// updates defaultFinalizerName or its override. -func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource *v1alpha1.Topic) (*v1alpha1.Topic, error) { - - getter := r.Lister.Topics(resource.Namespace) - - actual, err := getter.Get(resource.Name) - if err != nil { - return resource, err - } - - // Don't modify the informers copy. - existing := actual.DeepCopy() - - var finalizers []string - - // If there's nothing to update, just return. - existingFinalizers := sets.NewString(existing.Finalizers...) - desiredFinalizers := sets.NewString(resource.Finalizers...) - - if desiredFinalizers.Has(r.finalizerName) { - if existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Add the finalizer. - finalizers = append(existing.Finalizers, r.finalizerName) - } else { - if !existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Remove the finalizer. - existingFinalizers.Delete(r.finalizerName) - finalizers = existingFinalizers.List() - } - - mergePatch := map[string]interface{}{ - "metadata": map[string]interface{}{ - "finalizers": finalizers, - "resourceVersion": existing.ResourceVersion, - }, - } - - patch, err := json.Marshal(mergePatch) - if err != nil { - return resource, err - } - - patcher := r.Client.InternalV1alpha1().Topics(resource.Namespace) - - resourceName := resource.Name - resource, err = patcher.Patch(resourceName, types.MergePatchType, patch) - if err != nil { - r.Recorder.Eventf(resource, v1.EventTypeWarning, "FinalizerUpdateFailed", - "Failed to update finalizers for %q: %v", resourceName, err) - } else { - r.Recorder.Eventf(resource, v1.EventTypeNormal, "FinalizerUpdate", - "Updated %q finalizers", resource.GetName()) - } - return resource, err -} - -func (r *reconcilerImpl) setFinalizerIfFinalizer(ctx context.Context, resource *v1alpha1.Topic) (*v1alpha1.Topic, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - // If this resource is not being deleted, mark the finalizer. - if resource.GetDeletionTimestamp().IsZero() { - finalizers.Insert(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} - -func (r *reconcilerImpl) clearFinalizer(ctx context.Context, resource *v1alpha1.Topic, reconcileEvent reconciler.Event) (*v1alpha1.Topic, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - if resource.GetDeletionTimestamp().IsZero() { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - if event.EventType == v1.EventTypeNormal { - finalizers.Delete(r.finalizerName) - } - } - } else { - finalizers.Delete(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} diff --git a/pkg/client/injection/reconciler/intevents/v1alpha1/topic/stub/controller.go b/pkg/client/injection/reconciler/intevents/v1alpha1/topic/stub/controller.go deleted file mode 100644 index 1c02b0380c..0000000000 --- a/pkg/client/injection/reconciler/intevents/v1alpha1/topic/stub/controller.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package topic - -import ( - context "context" - - topic "github.com/google/knative-gcp/pkg/client/injection/informers/intevents/v1alpha1/topic" - v1alpha1topic "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/topic" - configmap "knative.dev/pkg/configmap" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// NewController creates a Reconciler for Topic and returns the result of NewImpl. -func NewController( - ctx context.Context, - cmw configmap.Watcher, -) *controller.Impl { - logger := logging.FromContext(ctx) - - topicInformer := topic.Get(ctx) - - // TODO: setup additional informers here. - - r := &Reconciler{} - impl := v1alpha1topic.NewImpl(ctx, r) - - logger.Info("Setting up event handlers.") - - topicInformer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue)) - - // TODO: add additional informer event handlers here. - - return impl -} diff --git a/pkg/client/injection/reconciler/intevents/v1alpha1/topic/stub/reconciler.go b/pkg/client/injection/reconciler/intevents/v1alpha1/topic/stub/reconciler.go deleted file mode 100644 index 0d4dc830f6..0000000000 --- a/pkg/client/injection/reconciler/intevents/v1alpha1/topic/stub/reconciler.go +++ /dev/null @@ -1,87 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package topic - -import ( - context "context" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1" - topic "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/topic" - v1 "k8s.io/api/core/v1" - reconciler "knative.dev/pkg/reconciler" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// newReconciledNormal makes a new reconciler event with event type Normal, and -// reason TopicReconciled. -func newReconciledNormal(namespace, name string) reconciler.Event { - return reconciler.NewEvent(v1.EventTypeNormal, "TopicReconciled", "Topic reconciled: \"%s/%s\"", namespace, name) -} - -// Reconciler implements controller.Reconciler for Topic resources. -type Reconciler struct { - // TODO: add additional requirements here. -} - -// Check that our Reconciler implements Interface -var _ topic.Interface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements Finalizer -//var _ topic.Finalizer = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyInterface -// Implement this to observe resources even when we are not the leader. -//var _ topic.ReadOnlyInterface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyFinalizer -// Implement this to observe tombstoned resources even when we are not -// the leader (best effort). -//var _ topic.ReadOnlyFinalizer = (*Reconciler)(nil) - -// ReconcileKind implements Interface.ReconcileKind. -func (r *Reconciler) ReconcileKind(ctx context.Context, o *v1alpha1.Topic) reconciler.Event { - // TODO: use this if the resource implements InitializeConditions. - // o.Status.InitializeConditions() - - // TODO: add custom reconciliation logic here. - - // TODO: use this if the object has .status.ObservedGeneration. - // o.Status.ObservedGeneration = o.Generation - return newReconciledNormal(o.Namespace, o.Name) -} - -// Optionally, use FinalizeKind to add finalizers. FinalizeKind will be called -// when the resource is deleted. -//func (r *Reconciler) FinalizeKind(ctx context.Context, o *v1alpha1.Topic) reconciler.Event { -// // TODO: add custom finalization logic here. -// return nil -//} - -// Optionally, use ObserveKind to observe the resource when we are not the leader. -// func (r *Reconciler) ObserveKind(ctx context.Context, o *v1alpha1.Topic) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -// } - -// Optionally, use ObserveFinalizeKind to observe resources being finalized when we are no the leader. -//func (r *Reconciler) ObserveFinalizeKind(ctx context.Context, o *v1alpha1.Topic) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -//} diff --git a/pkg/client/injection/reconciler/messaging/v1alpha1/channel/controller.go b/pkg/client/injection/reconciler/messaging/v1alpha1/channel/controller.go deleted file mode 100644 index b18bc720e1..0000000000 --- a/pkg/client/injection/reconciler/messaging/v1alpha1/channel/controller.go +++ /dev/null @@ -1,139 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package channel - -import ( - context "context" - fmt "fmt" - reflect "reflect" - strings "strings" - - versionedscheme "github.com/google/knative-gcp/pkg/client/clientset/versioned/scheme" - client "github.com/google/knative-gcp/pkg/client/injection/client" - channel "github.com/google/knative-gcp/pkg/client/injection/informers/messaging/v1alpha1/channel" - corev1 "k8s.io/api/core/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - scheme "k8s.io/client-go/kubernetes/scheme" - v1 "k8s.io/client-go/kubernetes/typed/core/v1" - record "k8s.io/client-go/tools/record" - kubeclient "knative.dev/pkg/client/injection/kube/client" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -const ( - defaultControllerAgentName = "channel-controller" - defaultFinalizerName = "channels.messaging.cloud.google.com" -) - -// NewImpl returns a controller.Impl that handles queuing and feeding work from -// the queue through an implementation of controller.Reconciler, delegating to -// the provided Interface and optional Finalizer methods. OptionsFn is used to return -// controller.Options to be used but the internal reconciler. -func NewImpl(ctx context.Context, r Interface, optionsFns ...controller.OptionsFn) *controller.Impl { - logger := logging.FromContext(ctx) - - // Check the options function input. It should be 0 or 1. - if len(optionsFns) > 1 { - logger.Fatalf("up to one options function is supported, found %d", len(optionsFns)) - } - - channelInformer := channel.Get(ctx) - - lister := channelInformer.Lister() - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client.Get(ctx), - Lister: lister, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - t := reflect.TypeOf(r).Elem() - queueName := fmt.Sprintf("%s.%s", strings.ReplaceAll(t.PkgPath(), "/", "-"), t.Name()) - - impl := controller.NewImpl(rec, logger, queueName) - agentName := defaultControllerAgentName - - // Pass impl to the options. Save any optional results. - for _, fn := range optionsFns { - opts := fn(impl) - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - if opts.AgentName != "" { - agentName = opts.AgentName - } - } - - rec.Recorder = createRecorder(ctx, agentName) - - return impl -} - -func createRecorder(ctx context.Context, agentName string) record.EventRecorder { - logger := logging.FromContext(ctx) - - recorder := controller.GetEventRecorder(ctx) - if recorder == nil { - // Create event broadcaster - logger.Debug("Creating event broadcaster") - eventBroadcaster := record.NewBroadcaster() - watches := []watch.Interface{ - eventBroadcaster.StartLogging(logger.Named("event-broadcaster").Infof), - eventBroadcaster.StartRecordingToSink( - &v1.EventSinkImpl{Interface: kubeclient.Get(ctx).CoreV1().Events("")}), - } - recorder = eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: agentName}) - go func() { - <-ctx.Done() - for _, w := range watches { - w.Stop() - } - }() - } - - return recorder -} - -func init() { - versionedscheme.AddToScheme(scheme.Scheme) -} diff --git a/pkg/client/injection/reconciler/messaging/v1alpha1/channel/reconciler.go b/pkg/client/injection/reconciler/messaging/v1alpha1/channel/reconciler.go deleted file mode 100644 index ee8b770a85..0000000000 --- a/pkg/client/injection/reconciler/messaging/v1alpha1/channel/reconciler.go +++ /dev/null @@ -1,434 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package channel - -import ( - context "context" - json "encoding/json" - fmt "fmt" - reflect "reflect" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/messaging/v1alpha1" - versioned "github.com/google/knative-gcp/pkg/client/clientset/versioned" - messagingv1alpha1 "github.com/google/knative-gcp/pkg/client/listers/messaging/v1alpha1" - zap "go.uber.org/zap" - v1 "k8s.io/api/core/v1" - equality "k8s.io/apimachinery/pkg/api/equality" - errors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - sets "k8s.io/apimachinery/pkg/util/sets" - cache "k8s.io/client-go/tools/cache" - record "k8s.io/client-go/tools/record" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" - reconciler "knative.dev/pkg/reconciler" -) - -// Interface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.Channel. -type Interface interface { - // ReconcileKind implements custom logic to reconcile v1alpha1.Channel. Any changes - // to the objects .Status or .Finalizers will be propagated to the stored - // object. It is recommended that implementors do not call any update calls - // for the Kind inside of ReconcileKind, it is the responsibility of the calling - // controller to propagate those properties. The resource passed to ReconcileKind - // will always have an empty deletion timestamp. - ReconcileKind(ctx context.Context, o *v1alpha1.Channel) reconciler.Event -} - -// Finalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.Channel. -type Finalizer interface { - // FinalizeKind implements custom logic to finalize v1alpha1.Channel. Any changes - // to the objects .Status or .Finalizers will be ignored. Returning a nil or - // Normal type reconciler.Event will allow the finalizer to be deleted on - // the resource. The resource passed to FinalizeKind will always have a set - // deletion timestamp. - FinalizeKind(ctx context.Context, o *v1alpha1.Channel) reconciler.Event -} - -// ReadOnlyInterface defines the strongly typed interfaces to be implemented by a -// controller reconciling v1alpha1.Channel if they want to process resources for which -// they are not the leader. -type ReadOnlyInterface interface { - // ObserveKind implements logic to observe v1alpha1.Channel. - // This method should not write to the API. - ObserveKind(ctx context.Context, o *v1alpha1.Channel) reconciler.Event -} - -// ReadOnlyFinalizer defines the strongly typed interfaces to be implemented by a -// controller finalizing v1alpha1.Channel if they want to process tombstoned resources -// even when they are not the leader. Due to the nature of how finalizers are handled -// there are no guarantees that this will be called. -type ReadOnlyFinalizer interface { - // ObserveFinalizeKind implements custom logic to observe the final state of v1alpha1.Channel. - // This method should not write to the API. - ObserveFinalizeKind(ctx context.Context, o *v1alpha1.Channel) reconciler.Event -} - -// reconcilerImpl implements controller.Reconciler for v1alpha1.Channel resources. -type reconcilerImpl struct { - // LeaderAwareFuncs is inlined to help us implement reconciler.LeaderAware - reconciler.LeaderAwareFuncs - - // Client is used to write back status updates. - Client versioned.Interface - - // Listers index properties about resources - Lister messagingv1alpha1.ChannelLister - - // Recorder is an event recorder for recording Event resources to the - // Kubernetes API. - Recorder record.EventRecorder - - // configStore allows for decorating a context with config maps. - // +optional - configStore reconciler.ConfigStore - - // reconciler is the implementation of the business logic of the resource. - reconciler Interface - - // finalizerName is the name of the finalizer to reconcile. - finalizerName string -} - -// Check that our Reconciler implements controller.Reconciler -var _ controller.Reconciler = (*reconcilerImpl)(nil) - -// Check that our generated Reconciler is always LeaderAware. -var _ reconciler.LeaderAware = (*reconcilerImpl)(nil) - -func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versioned.Interface, lister messagingv1alpha1.ChannelLister, recorder record.EventRecorder, r Interface, options ...controller.Options) controller.Reconciler { - // Check the options function input. It should be 0 or 1. - if len(options) > 1 { - logger.Fatalf("up to one options struct is supported, found %d", len(options)) - } - - // Fail fast when users inadvertently implement the other LeaderAware interface. - // For the typed reconcilers, Promote shouldn't take any arguments. - if _, ok := r.(reconciler.LeaderAware); ok { - logger.Fatalf("%T implements the incorrect LeaderAware interface. Promote() should not take an argument as genreconciler handles the enqueuing automatically.", r) - } - // TODO: Consider validating when folks implement ReadOnlyFinalizer, but not Finalizer. - - rec := &reconcilerImpl{ - LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ - PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { - all, err := lister.List(labels.Everything()) - if err != nil { - return err - } - for _, elt := range all { - // TODO: Consider letting users specify a filter in options. - enq(bkt, types.NamespacedName{ - Namespace: elt.GetNamespace(), - Name: elt.GetName(), - }) - } - return nil - }, - }, - Client: client, - Lister: lister, - Recorder: recorder, - reconciler: r, - finalizerName: defaultFinalizerName, - } - - for _, opts := range options { - if opts.ConfigStore != nil { - rec.configStore = opts.ConfigStore - } - if opts.FinalizerName != "" { - rec.finalizerName = opts.FinalizerName - } - } - - return rec -} - -// Reconcile implements controller.Reconciler -func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { - logger := logging.FromContext(ctx) - - // Convert the namespace/name string into a distinct namespace and name - namespace, name, err := cache.SplitMetaNamespaceKey(key) - if err != nil { - logger.Errorf("invalid resource key: %s", key) - return nil - } - // Establish whether we are the leader for use below. - isLeader := r.IsLeaderFor(types.NamespacedName{ - Namespace: namespace, - Name: name, - }) - roi, isROI := r.reconciler.(ReadOnlyInterface) - rof, isROF := r.reconciler.(ReadOnlyFinalizer) - if !isLeader && !isROI && !isROF { - // If we are not the leader, and we don't implement either ReadOnly - // interface, then take a fast-path out. - return nil - } - - // If configStore is set, attach the frozen configuration to the context. - if r.configStore != nil { - ctx = r.configStore.ToContext(ctx) - } - - // Add the recorder to context. - ctx = controller.WithEventRecorder(ctx, r.Recorder) - - // Get the resource with this namespace/name. - - getter := r.Lister.Channels(namespace) - - original, err := getter.Get(name) - - if errors.IsNotFound(err) { - // The resource may no longer exist, in which case we stop processing. - logger.Debugf("resource %q no longer exists", key) - return nil - } else if err != nil { - return err - } - - // Don't modify the informers copy. - resource := original.DeepCopy() - - var reconcileEvent reconciler.Event - if resource.GetDeletionTimestamp().IsZero() { - if isLeader { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ReconcileKind")) - - // Set and update the finalizer on resource if r.reconciler - // implements Finalizer. - if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil { - return fmt.Errorf("failed to set finalizers: %w", err) - } - - reconciler.PreProcessReconcile(ctx, resource) - - // Reconcile this copy of the resource and then write back any status - // updates regardless of whether the reconciliation errored out. - reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) - - reconciler.PostProcessReconcile(ctx, resource, original) - - } else if isROI { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveKind")) - - // Observe any changes to this resource, since we are not the leader. - reconcileEvent = roi.ObserveKind(ctx, resource) - } - } else if fin, ok := r.reconciler.(Finalizer); isLeader && ok { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "FinalizeKind")) - - // For finalizing reconcilers, if this resource being marked for deletion - // and reconciled cleanly (nil or normal event), remove the finalizer. - reconcileEvent = fin.FinalizeKind(ctx, resource) - if resource, err = r.clearFinalizer(ctx, resource, reconcileEvent); err != nil { - return fmt.Errorf("failed to clear finalizers: %w", err) - } - } else if !isLeader && isROF { - // Append the target method to the logger. - logger = logger.With(zap.String("targetMethod", "ObserveFinalizeKind")) - - // For finalizing reconcilers, just observe when we aren't the leader. - reconcileEvent = rof.ObserveFinalizeKind(ctx, resource) - } - - // Synchronize the status. - if equality.Semantic.DeepEqual(original.Status, resource.Status) { - // If we didn't change anything then don't call updateStatus. - // This is important because the copy we loaded from the injectionInformer's - // cache may be stale and we don't want to overwrite a prior update - // to status with this stale state. - } else if !isLeader { - logger.Warn("Saw status changes when we aren't the leader!") - // TODO: Consider logging the diff at Debug? - } else if err = r.updateStatus(original, resource); err != nil { - logger.Warnw("Failed to update resource status", zap.Error(err)) - r.Recorder.Eventf(resource, v1.EventTypeWarning, "UpdateFailed", - "Failed to update status for %q: %v", resource.Name, err) - return err - } - - // Report the reconciler event, if any. - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - logger.Infow("Returned an event", zap.Any("event", reconcileEvent)) - r.Recorder.Eventf(resource, event.EventType, event.Reason, event.Format, event.Args...) - - // the event was wrapped inside an error, consider the reconciliation as failed - if _, isEvent := reconcileEvent.(*reconciler.ReconcilerEvent); !isEvent { - return reconcileEvent - } - return nil - } - - logger.Errorw("Returned an error", zap.Error(reconcileEvent)) - r.Recorder.Event(resource, v1.EventTypeWarning, "InternalError", reconcileEvent.Error()) - return reconcileEvent - } - - return nil -} - -func (r *reconcilerImpl) updateStatus(existing *v1alpha1.Channel, desired *v1alpha1.Channel) error { - existing = existing.DeepCopy() - return reconciler.RetryUpdateConflicts(func(attempts int) (err error) { - // The first iteration tries to use the injectionInformer's state, subsequent attempts fetch the latest state via API. - if attempts > 0 { - - getter := r.Client.MessagingV1alpha1().Channels(desired.Namespace) - - existing, err = getter.Get(desired.Name, metav1.GetOptions{}) - if err != nil { - return err - } - } - - // If there's nothing to update, just return. - if reflect.DeepEqual(existing.Status, desired.Status) { - return nil - } - - existing.Status = desired.Status - - updater := r.Client.MessagingV1alpha1().Channels(existing.Namespace) - - _, err = updater.UpdateStatus(existing) - return err - }) -} - -// updateFinalizersFiltered will update the Finalizers of the resource. -// TODO: this method could be generic and sync all finalizers. For now it only -// updates defaultFinalizerName or its override. -func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource *v1alpha1.Channel) (*v1alpha1.Channel, error) { - - getter := r.Lister.Channels(resource.Namespace) - - actual, err := getter.Get(resource.Name) - if err != nil { - return resource, err - } - - // Don't modify the informers copy. - existing := actual.DeepCopy() - - var finalizers []string - - // If there's nothing to update, just return. - existingFinalizers := sets.NewString(existing.Finalizers...) - desiredFinalizers := sets.NewString(resource.Finalizers...) - - if desiredFinalizers.Has(r.finalizerName) { - if existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Add the finalizer. - finalizers = append(existing.Finalizers, r.finalizerName) - } else { - if !existingFinalizers.Has(r.finalizerName) { - // Nothing to do. - return resource, nil - } - // Remove the finalizer. - existingFinalizers.Delete(r.finalizerName) - finalizers = existingFinalizers.List() - } - - mergePatch := map[string]interface{}{ - "metadata": map[string]interface{}{ - "finalizers": finalizers, - "resourceVersion": existing.ResourceVersion, - }, - } - - patch, err := json.Marshal(mergePatch) - if err != nil { - return resource, err - } - - patcher := r.Client.MessagingV1alpha1().Channels(resource.Namespace) - - resourceName := resource.Name - resource, err = patcher.Patch(resourceName, types.MergePatchType, patch) - if err != nil { - r.Recorder.Eventf(resource, v1.EventTypeWarning, "FinalizerUpdateFailed", - "Failed to update finalizers for %q: %v", resourceName, err) - } else { - r.Recorder.Eventf(resource, v1.EventTypeNormal, "FinalizerUpdate", - "Updated %q finalizers", resource.GetName()) - } - return resource, err -} - -func (r *reconcilerImpl) setFinalizerIfFinalizer(ctx context.Context, resource *v1alpha1.Channel) (*v1alpha1.Channel, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - // If this resource is not being deleted, mark the finalizer. - if resource.GetDeletionTimestamp().IsZero() { - finalizers.Insert(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} - -func (r *reconcilerImpl) clearFinalizer(ctx context.Context, resource *v1alpha1.Channel, reconcileEvent reconciler.Event) (*v1alpha1.Channel, error) { - if _, ok := r.reconciler.(Finalizer); !ok { - return resource, nil - } - if resource.GetDeletionTimestamp().IsZero() { - return resource, nil - } - - finalizers := sets.NewString(resource.Finalizers...) - - if reconcileEvent != nil { - var event *reconciler.ReconcilerEvent - if reconciler.EventAs(reconcileEvent, &event) { - if event.EventType == v1.EventTypeNormal { - finalizers.Delete(r.finalizerName) - } - } - } else { - finalizers.Delete(r.finalizerName) - } - - resource.Finalizers = finalizers.List() - - // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource) -} diff --git a/pkg/client/injection/reconciler/messaging/v1alpha1/channel/stub/controller.go b/pkg/client/injection/reconciler/messaging/v1alpha1/channel/stub/controller.go deleted file mode 100644 index 933865d541..0000000000 --- a/pkg/client/injection/reconciler/messaging/v1alpha1/channel/stub/controller.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package channel - -import ( - context "context" - - channel "github.com/google/knative-gcp/pkg/client/injection/informers/messaging/v1alpha1/channel" - v1alpha1channel "github.com/google/knative-gcp/pkg/client/injection/reconciler/messaging/v1alpha1/channel" - configmap "knative.dev/pkg/configmap" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// NewController creates a Reconciler for Channel and returns the result of NewImpl. -func NewController( - ctx context.Context, - cmw configmap.Watcher, -) *controller.Impl { - logger := logging.FromContext(ctx) - - channelInformer := channel.Get(ctx) - - // TODO: setup additional informers here. - - r := &Reconciler{} - impl := v1alpha1channel.NewImpl(ctx, r) - - logger.Info("Setting up event handlers.") - - channelInformer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue)) - - // TODO: add additional informer event handlers here. - - return impl -} diff --git a/pkg/client/injection/reconciler/messaging/v1alpha1/channel/stub/reconciler.go b/pkg/client/injection/reconciler/messaging/v1alpha1/channel/stub/reconciler.go deleted file mode 100644 index 9c267fb126..0000000000 --- a/pkg/client/injection/reconciler/messaging/v1alpha1/channel/stub/reconciler.go +++ /dev/null @@ -1,87 +0,0 @@ -/* -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. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package channel - -import ( - context "context" - - v1alpha1 "github.com/google/knative-gcp/pkg/apis/messaging/v1alpha1" - channel "github.com/google/knative-gcp/pkg/client/injection/reconciler/messaging/v1alpha1/channel" - v1 "k8s.io/api/core/v1" - reconciler "knative.dev/pkg/reconciler" -) - -// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT - -// newReconciledNormal makes a new reconciler event with event type Normal, and -// reason ChannelReconciled. -func newReconciledNormal(namespace, name string) reconciler.Event { - return reconciler.NewEvent(v1.EventTypeNormal, "ChannelReconciled", "Channel reconciled: \"%s/%s\"", namespace, name) -} - -// Reconciler implements controller.Reconciler for Channel resources. -type Reconciler struct { - // TODO: add additional requirements here. -} - -// Check that our Reconciler implements Interface -var _ channel.Interface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements Finalizer -//var _ channel.Finalizer = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyInterface -// Implement this to observe resources even when we are not the leader. -//var _ channel.ReadOnlyInterface = (*Reconciler)(nil) - -// Optionally check that our Reconciler implements ReadOnlyFinalizer -// Implement this to observe tombstoned resources even when we are not -// the leader (best effort). -//var _ channel.ReadOnlyFinalizer = (*Reconciler)(nil) - -// ReconcileKind implements Interface.ReconcileKind. -func (r *Reconciler) ReconcileKind(ctx context.Context, o *v1alpha1.Channel) reconciler.Event { - // TODO: use this if the resource implements InitializeConditions. - // o.Status.InitializeConditions() - - // TODO: add custom reconciliation logic here. - - // TODO: use this if the object has .status.ObservedGeneration. - // o.Status.ObservedGeneration = o.Generation - return newReconciledNormal(o.Namespace, o.Name) -} - -// Optionally, use FinalizeKind to add finalizers. FinalizeKind will be called -// when the resource is deleted. -//func (r *Reconciler) FinalizeKind(ctx context.Context, o *v1alpha1.Channel) reconciler.Event { -// // TODO: add custom finalization logic here. -// return nil -//} - -// Optionally, use ObserveKind to observe the resource when we are not the leader. -// func (r *Reconciler) ObserveKind(ctx context.Context, o *v1alpha1.Channel) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -// } - -// Optionally, use ObserveFinalizeKind to observe resources being finalized when we are no the leader. -//func (r *Reconciler) ObserveFinalizeKind(ctx context.Context, o *v1alpha1.Channel) reconciler.Event { -// // TODO: add custom observation logic here. -// return nil -//} diff --git a/pkg/pubsub/adapter/adapter_test.go b/pkg/pubsub/adapter/adapter_test.go index 41994c9b4d..9e53141520 100644 --- a/pkg/pubsub/adapter/adapter_test.go +++ b/pkg/pubsub/adapter/adapter_test.go @@ -16,169 +16,163 @@ limitations under the License. package adapter +import ( + "context" + "errors" + cepubsub "github.com/cloudevents/sdk-go/protocol/pubsub/v2" + cev2 "github.com/cloudevents/sdk-go/v2" + "github.com/cloudevents/sdk-go/v2/binding" + cehttp "github.com/cloudevents/sdk-go/v2/protocol/http" + "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" + "github.com/google/knative-gcp/pkg/utils/clients" + "io" + "net/http" + "net/http/httptest" + "testing" + "time" -// TODO fix all + "cloud.google.com/go/pubsub" + "cloud.google.com/go/pubsub/pstest" + "github.com/cloudevents/sdk-go/v2/event" + "google.golang.org/api/option" + "google.golang.org/grpc" +) + +const ( + testProjectID = "test-testProjectID" + testTopic = "test-testTopic" + testSub = "test-testSub" + testName = "test-testName" + testNamespace = "test-testNamespace" + testResourceGroup = "test-testResourceGroup" + testConverterType = "test-testConverterType" +) + +func testPubsubClient(ctx context.Context, t *testing.T, projectID string) (*pubsub.Client, func()) { + t.Helper() + srv := pstest.NewServer() + conn, err := grpc.Dial(srv.Addr, grpc.WithInsecure()) + if err != nil { + t.Fatalf("failed to dial test pubsub connection: %v", err) + } + close := func() { + srv.Close() + conn.Close() + } + c, err := pubsub.NewClient(ctx, projectID, option.WithGRPCConn(conn)) + if err != nil { + t.Fatalf("failed to create test pubsub client: %v", err) + } + return c, close +} + +type mockStatsReporter struct { + gotArgs *ReportArgs + gotCode int +} + +func (r *mockStatsReporter) ReportEventCount(args *ReportArgs, responseCode int) error { + r.gotArgs = args + r.gotCode = responseCode + return nil +} + +type mockConverter struct { + wantErr bool + wantEvent *cev2.Event +} + +func (c *mockConverter) Convert(ctx context.Context, msg *pubsub.Message, converterType converters.ConverterType) (*cev2.Event, error) { + if c.wantErr { + return nil, errors.New("induced error") + } + return c.wantEvent, nil +} + +func TestAdapter(t *testing.T) { + ctx := context.Background() + c, close := testPubsubClient(ctx, t, testProjectID) + defer close() + + topic, err := c.CreateTopic(ctx, testTopic) + if err != nil { + t.Fatalf("failed to create topic: %v", err) + } + sub, err := c.CreateSubscription(ctx, testSub, pubsub.SubscriptionConfig{ + Topic: topic, + }) + if err != nil { + t.Fatalf("failed to create subscription: %v", err) + } + + p, err := cepubsub.New(context.Background(), + cepubsub.WithClient(c), + cepubsub.WithProjectID(testProjectID), + cepubsub.WithTopicID(testTopic), + ) + if err != nil { + t.Fatalf("failed to create cloudevents pubsub protocol: %v", err) + } + + outbound := http.DefaultClient + + sinkClient, err := cehttp.New() + if err != nil { + t.Fatalf("failed to create sink cloudevents client: %v", err) + } + sinkSvr := httptest.NewServer(sinkClient) + defer sinkSvr.Close() + + converter := &mockConverter{} + reporter := &mockStatsReporter{} + args := &AdapterArgs{ + TopicID: testTopic, + SinkURI: sinkSvr.URL, + Extensions: map[string]string{}, + ConverterType: converters.ConverterType(testConverterType), + } + adapter := NewAdapter(ctx, + clients.ProjectID(testProjectID), + Namespace(testNamespace), + Name(testName), + ResourceGroup(testResourceGroup), + sub, + outbound, + converter, + reporter, + args) + + adapter.Start(ctx, func(_ error) {}) + defer adapter.Stop() + + testEvent := event.New() + testEvent.SetID("id") + testEvent.SetSource("source") + testEvent.SetSubject("subject") + testEvent.SetType("type") + + rctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + + go func() { + _, err := sinkClient.Receive(rctx) + if err != nil && err != io.EOF { + t.Errorf("unexpected error from sink receiving event: %v", err) + } + }() + + if err := p.Send(ctx, binding.ToMessage(&testEvent)); err != nil { + t.Fatalf("failed to seed event to pubsub: %v", err) + } + + <-rctx.Done() + + //res := topic.Publish(context.Background(), &pubsub.Message{ID: "testid"}) + //if _, err := res.Get(context.Background()); err != nil { + // t.Fatalf("Failed to publish a msg to topic: %v", err) + //} +} -//type mockStatsReporter struct { -// gotArgs *ReportArgs -// gotCode int -//} -// -//func (r *mockStatsReporter) ReportEventCount(args *ReportArgs, responseCode int) error { -// r.gotArgs = args -// r.gotCode = responseCode -// return nil -//} -// -//func TestStartAdapter(t *testing.T) { -// t.Skipf("need to fix the error from call to newPubSubClient: %s", `pubsub: google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.`) -// a := Adapter{ -// Project: "proj", -// Topic: "top", -// Subscription: "sub", -// Sink: "http://localhost:8081", -// Transformer: "http://localhost:8080", -// ExtensionsBase64: "eyJrZXkxIjoidmFsdWUxIiwia2V5MiI6InZhbHVlMiJ9Cg==", -// } -// // This test only does sanity checks to see if all fields are -// // initialized. -// // In reality, Start should be a blocking function. Here, it's not -// // blocking because we expect it to fail as it shouldn't be able to -// // connect to pubsub. -// if err := a.Start(context.Background()); err == nil { -// t.Fatal("adapter.Start got nil want error") -// } -// -// if a.SendMode == "" { -// t.Errorf("adapter.SendMode got %q want %q", a.SendMode, converters.DefaultSendMode) -// } -// if a.reporter == nil { -// t.Error("adapter.reporter got nil want a StatsReporter") -// } -// if a.inbound == nil { -// t.Error("adapter.inbound got nil want a cloudevents.Client") -// } -// if a.outbound == nil { -// t.Error("adapter.outbound got nil want a cloudevents.Client") -// } -// if a.transformer == nil { -// t.Error("adapter.transformer got nil want a cloudevents.Client") -// } -// wantExt := map[string]string{"key1": "value1", "key2": "value2"} -// if !cmp.Equal(wantExt, a.extensions) { -// t.Errorf("adapter.extensions got %v want %v", a.extensions, wantExt) -// } -//} -// -//func TestInboundConvert(t *testing.T) { -// cases := []struct { -// name string -// ctx context.Context -// message *cepubsub.Message -// wantMessageFn func() *cloudevents.Event -// wantErr bool -// }{{ -// name: "pubsub event", -// ctx: pubsubcontext.WithTransportContext( -// context.Background(), -// pubsubcontext.NewTransportContext( -// "proj", "topic", "sub", "test", -// &pubsub.Message{ID: "abc"}, -// ), -// ), -// message: &cepubsub.Message{ -// Data: []byte("some data"), -// Attributes: map[string]string{ -// "schema": "http://example.com", -// "key1": "value1", -// }, -// }, -// wantMessageFn: func() *cloudevents.Event { -// e := cloudevents.NewEvent(cloudevents.VersionV1) -// e.SetID("abc") -// e.SetSource(v1alpha1.CloudPubSubSourceEventSource("proj", "topic")) -// e.SetDataContentType("application/octet-stream") -// e.SetType(v1alpha1.CloudPubSubSourcePublish) -// e.SetDataSchema("http://example.com") -// e.SetExtension("knativecemode", string(converters.DefaultSendMode)) -// e.Data = []byte("some data") -// e.DataEncoded = true -// e.SetExtension("key1", "value1") -// return &e -// }, -// }, { -// name: "storage event", -// ctx: pubsubcontext.WithTransportContext( -// context.Background(), -// pubsubcontext.NewTransportContext( -// "proj", "topic", "sub", "test", -// &pubsub.Message{ID: "abc"}, -// ), -// ), -// message: &cepubsub.Message{ -// Data: []byte("some data"), -// Attributes: map[string]string{ -// "knative-gcp": "com.google.cloud.storage", -// "bucketId": "my-bucket", -// "objectId": "my-obj", -// "key1": "value1", -// "eventType": "OBJECT_FINALIZE", -// }, -// }, -// wantMessageFn: func() *cloudevents.Event { -// e := cloudevents.NewEvent(cloudevents.VersionV1) -// e.SetID("abc") -// e.SetSource(v1alpha1.CloudStorageSourceEventSource("my-bucket")) -// e.SetSubject("my-obj") -// e.SetDataContentType(*cloudevents.StringOfApplicationJSON()) -// e.SetType("com.google.cloud.storage.object.finalize") -// e.SetDataSchema("https://raw.githubusercontent.com/google/knative-gcp/master/schemas/storage/schema.json") -// e.Data = []byte("some data") -// e.DataEncoded = true -// e.SetExtension("key1", "value1") -// return &e -// }, -// }, { -// name: "invalid storage event", -// ctx: pubsubcontext.WithTransportContext( -// context.Background(), -// pubsubcontext.NewTransportContext( -// "proj", "topic", "sub", "test", -// &pubsub.Message{ID: "abc"}, -// ), -// ), -// message: &cepubsub.Message{ -// Data: []byte("some data"), -// Attributes: map[string]string{ -// "knative-gcp": "com.google.cloud.storage", -// "key1": "value1", -// "eventType": "OBJECT_FINALIZE", -// }, -// }, -// wantMessageFn: func() *cloudevents.Event { return nil }, -// wantErr: true, -// }} -// -// for _, tc := range cases { -// t.Run(tc.name, func(t *testing.T) { -// a := Adapter{ -// Project: "proj", -// Topic: "top", -// Subscription: "sub", -// SendMode: converters.DefaultSendMode, -// } -// var err error -// gotEvent, err := a.convert(tc.ctx, tc.message, err) -// if (err != nil) != tc.wantErr { -// t.Errorf("adapter.convert got error %v want error=%v", err, tc.wantErr) -// } -// if diff := cmp.Diff(tc.wantMessageFn(), gotEvent); diff != "" { -// t.Errorf("adapter.convert got unexpeceted cloudevents.Event (-want +got) %s", diff) -// } -// }) -// } -//} -// //func TestReceive(t *testing.T) { // cases := []struct { // name string From 02611c4f07eaad70b9ad4785ddc690607d5a30f9 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Tue, 23 Jun 2020 17:23:52 -0700 Subject: [PATCH 21/28] commenting out adapter tests for now.. will do in a follow up --- pkg/pubsub/adapter/adapter_test.go | 310 +++++++++++++++-------------- 1 file changed, 156 insertions(+), 154 deletions(-) diff --git a/pkg/pubsub/adapter/adapter_test.go b/pkg/pubsub/adapter/adapter_test.go index 9e53141520..3969ad3bbf 100644 --- a/pkg/pubsub/adapter/adapter_test.go +++ b/pkg/pubsub/adapter/adapter_test.go @@ -16,162 +16,164 @@ limitations under the License. package adapter -import ( - "context" - "errors" - cepubsub "github.com/cloudevents/sdk-go/protocol/pubsub/v2" - cev2 "github.com/cloudevents/sdk-go/v2" - "github.com/cloudevents/sdk-go/v2/binding" - cehttp "github.com/cloudevents/sdk-go/v2/protocol/http" - "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" - "github.com/google/knative-gcp/pkg/utils/clients" - "io" - "net/http" - "net/http/httptest" - "testing" - "time" +// TODO redo this tests in https://github.com/google/knative-gcp/issues/1333 - "cloud.google.com/go/pubsub" - "cloud.google.com/go/pubsub/pstest" - "github.com/cloudevents/sdk-go/v2/event" - "google.golang.org/api/option" - "google.golang.org/grpc" -) - -const ( - testProjectID = "test-testProjectID" - testTopic = "test-testTopic" - testSub = "test-testSub" - testName = "test-testName" - testNamespace = "test-testNamespace" - testResourceGroup = "test-testResourceGroup" - testConverterType = "test-testConverterType" -) - -func testPubsubClient(ctx context.Context, t *testing.T, projectID string) (*pubsub.Client, func()) { - t.Helper() - srv := pstest.NewServer() - conn, err := grpc.Dial(srv.Addr, grpc.WithInsecure()) - if err != nil { - t.Fatalf("failed to dial test pubsub connection: %v", err) - } - close := func() { - srv.Close() - conn.Close() - } - c, err := pubsub.NewClient(ctx, projectID, option.WithGRPCConn(conn)) - if err != nil { - t.Fatalf("failed to create test pubsub client: %v", err) - } - return c, close -} - -type mockStatsReporter struct { - gotArgs *ReportArgs - gotCode int -} - -func (r *mockStatsReporter) ReportEventCount(args *ReportArgs, responseCode int) error { - r.gotArgs = args - r.gotCode = responseCode - return nil -} - -type mockConverter struct { - wantErr bool - wantEvent *cev2.Event -} - -func (c *mockConverter) Convert(ctx context.Context, msg *pubsub.Message, converterType converters.ConverterType) (*cev2.Event, error) { - if c.wantErr { - return nil, errors.New("induced error") - } - return c.wantEvent, nil -} - -func TestAdapter(t *testing.T) { - ctx := context.Background() - c, close := testPubsubClient(ctx, t, testProjectID) - defer close() - - topic, err := c.CreateTopic(ctx, testTopic) - if err != nil { - t.Fatalf("failed to create topic: %v", err) - } - sub, err := c.CreateSubscription(ctx, testSub, pubsub.SubscriptionConfig{ - Topic: topic, - }) - if err != nil { - t.Fatalf("failed to create subscription: %v", err) - } - - p, err := cepubsub.New(context.Background(), - cepubsub.WithClient(c), - cepubsub.WithProjectID(testProjectID), - cepubsub.WithTopicID(testTopic), - ) - if err != nil { - t.Fatalf("failed to create cloudevents pubsub protocol: %v", err) - } - - outbound := http.DefaultClient - - sinkClient, err := cehttp.New() - if err != nil { - t.Fatalf("failed to create sink cloudevents client: %v", err) - } - sinkSvr := httptest.NewServer(sinkClient) - defer sinkSvr.Close() - - converter := &mockConverter{} - reporter := &mockStatsReporter{} - args := &AdapterArgs{ - TopicID: testTopic, - SinkURI: sinkSvr.URL, - Extensions: map[string]string{}, - ConverterType: converters.ConverterType(testConverterType), - } - adapter := NewAdapter(ctx, - clients.ProjectID(testProjectID), - Namespace(testNamespace), - Name(testName), - ResourceGroup(testResourceGroup), - sub, - outbound, - converter, - reporter, - args) - - adapter.Start(ctx, func(_ error) {}) - defer adapter.Stop() - - testEvent := event.New() - testEvent.SetID("id") - testEvent.SetSource("source") - testEvent.SetSubject("subject") - testEvent.SetType("type") - - rctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() - - go func() { - _, err := sinkClient.Receive(rctx) - if err != nil && err != io.EOF { - t.Errorf("unexpected error from sink receiving event: %v", err) - } - }() - - if err := p.Send(ctx, binding.ToMessage(&testEvent)); err != nil { - t.Fatalf("failed to seed event to pubsub: %v", err) - } - - <-rctx.Done() +//import ( +// "context" +// "errors" +// cepubsub "github.com/cloudevents/sdk-go/protocol/pubsub/v2" +// cev2 "github.com/cloudevents/sdk-go/v2" +// "github.com/cloudevents/sdk-go/v2/binding" +// cehttp "github.com/cloudevents/sdk-go/v2/protocol/http" +// "github.com/google/knative-gcp/pkg/pubsub/adapter/converters" +// "github.com/google/knative-gcp/pkg/utils/clients" +// "io" +// "net/http" +// "net/http/httptest" +// "testing" +// "time" +// +// "cloud.google.com/go/pubsub" +// "cloud.google.com/go/pubsub/pstest" +// "github.com/cloudevents/sdk-go/v2/event" +// "google.golang.org/api/option" +// "google.golang.org/grpc" +//) +// +//const ( +// testProjectID = "test-testProjectID" +// testTopic = "test-testTopic" +// testSub = "test-testSub" +// testName = "test-testName" +// testNamespace = "test-testNamespace" +// testResourceGroup = "test-testResourceGroup" +// testConverterType = "test-testConverterType" +//) +// +//func testPubsubClient(ctx context.Context, t *testing.T, projectID string) (*pubsub.Client, func()) { +// t.Helper() +// srv := pstest.NewServer() +// conn, err := grpc.Dial(srv.Addr, grpc.WithInsecure()) +// if err != nil { +// t.Fatalf("failed to dial test pubsub connection: %v", err) +// } +// close := func() { +// srv.Close() +// conn.Close() +// } +// c, err := pubsub.NewClient(ctx, projectID, option.WithGRPCConn(conn)) +// if err != nil { +// t.Fatalf("failed to create test pubsub client: %v", err) +// } +// return c, close +//} +// +//type mockStatsReporter struct { +// gotArgs *ReportArgs +// gotCode int +//} +// +//func (r *mockStatsReporter) ReportEventCount(args *ReportArgs, responseCode int) error { +// r.gotArgs = args +// r.gotCode = responseCode +// return nil +//} +// +//type mockConverter struct { +// wantErr bool +// wantEvent *cev2.Event +//} +// +//func (c *mockConverter) Convert(ctx context.Context, msg *pubsub.Message, converterType converters.ConverterType) (*cev2.Event, error) { +// if c.wantErr { +// return nil, errors.New("induced error") +// } +// return c.wantEvent, nil +//} +// +//func TestAdapter(t *testing.T) { +// ctx := context.Background() +// c, close := testPubsubClient(ctx, t, testProjectID) +// defer close() +// +// topic, err := c.CreateTopic(ctx, testTopic) +// if err != nil { +// t.Fatalf("failed to create topic: %v", err) +// } +// sub, err := c.CreateSubscription(ctx, testSub, pubsub.SubscriptionConfig{ +// Topic: topic, +// }) +// if err != nil { +// t.Fatalf("failed to create subscription: %v", err) +// } +// +// p, err := cepubsub.New(context.Background(), +// cepubsub.WithClient(c), +// cepubsub.WithProjectID(testProjectID), +// cepubsub.WithTopicID(testTopic), +// ) +// if err != nil { +// t.Fatalf("failed to create cloudevents pubsub protocol: %v", err) +// } +// +// outbound := http.DefaultClient +// +// sinkClient, err := cehttp.New() +// if err != nil { +// t.Fatalf("failed to create sink cloudevents client: %v", err) +// } +// sinkSvr := httptest.NewServer(sinkClient) +// defer sinkSvr.Close() +// +// converter := &mockConverter{} +// reporter := &mockStatsReporter{} +// args := &AdapterArgs{ +// TopicID: testTopic, +// SinkURI: sinkSvr.URL, +// Extensions: map[string]string{}, +// ConverterType: converters.ConverterType(testConverterType), +// } +// adapter := NewAdapter(ctx, +// clients.ProjectID(testProjectID), +// Namespace(testNamespace), +// Name(testName), +// ResourceGroup(testResourceGroup), +// sub, +// outbound, +// converter, +// reporter, +// args) +// +// adapter.Start(ctx, func(_ error) {}) +// defer adapter.Stop() +// +// testEvent := event.New() +// testEvent.SetID("id") +// testEvent.SetSource("source") +// testEvent.SetSubject("subject") +// testEvent.SetType("type") +// +// rctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) +// defer cancel() +// +// go func() { +// _, err := sinkClient.Receive(rctx) +// if err != nil && err != io.EOF { +// t.Errorf("unexpected error from sink receiving event: %v", err) +// } +// }() +// +// if err := p.Send(ctx, binding.ToMessage(&testEvent)); err != nil { +// t.Fatalf("failed to seed event to pubsub: %v", err) +// } +// +// <-rctx.Done() - //res := topic.Publish(context.Background(), &pubsub.Message{ID: "testid"}) - //if _, err := res.Get(context.Background()); err != nil { - // t.Fatalf("Failed to publish a msg to topic: %v", err) - //} -} +//res := topic.Publish(context.Background(), &pubsub.Message{ID: "testid"}) +//if _, err := res.Get(context.Background()); err != nil { +// t.Fatalf("Failed to publish a msg to topic: %v", err) +//} +//} //func TestReceive(t *testing.T) { // cases := []struct { From 223698b038517a1ff7494d2af94776e268f89aae Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Tue, 23 Jun 2020 17:32:03 -0700 Subject: [PATCH 22/28] address code review comment --- pkg/pubsub/adapter/adapter.go | 2 +- pkg/tracing/attributes.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/pubsub/adapter/adapter.go b/pkg/pubsub/adapter/adapter.go index 35be7f0e49..9dc2903ccf 100644 --- a/pkg/pubsub/adapter/adapter.go +++ b/pkg/pubsub/adapter/adapter.go @@ -250,7 +250,7 @@ func (a *Adapter) startSpan(ctx context.Context, event *cev2.Event) (context.Con // This receive adapter code is used both for Sources and Channels. // An ugly way to identify whether it was created from a Channel is to look at the resourceGroup. if a.resourceGroup == messaging.ChannelsResource.String() { - spanName = tracing.ChannelDestination(a.namespacedName) + spanName = tracing.SubscriptionDestination(a.subscription.ID()) } var span *trace.Span if dt, ok := extensions.GetDistributedTracingExtension(*event); ok { diff --git a/pkg/tracing/attributes.go b/pkg/tracing/attributes.go index 4808f5decc..4cdf91d386 100644 --- a/pkg/tracing/attributes.go +++ b/pkg/tracing/attributes.go @@ -31,8 +31,8 @@ var ( PubSubProtocolAttribute = tracing.MessagingProtocolAttribute(PubSubProtocol) ) -func ChannelDestination(c types.NamespacedName) string { - return fmt.Sprintf("channel:%s.%s", c.Name, c.Namespace) +func SubscriptionDestination(s string) string { + return fmt.Sprintf("subscription:%s", s) } func SourceDestination(resourceGroup string, src types.NamespacedName) string { From a11f04229a5f0422da4730f25aac161374308505 Mon Sep 17 00:00:00 2001 From: Cong Liu Date: Tue, 23 Jun 2020 17:58:37 -0700 Subject: [PATCH 23/28] Fix ut --- pkg/reconciler/brokercell/brokercell_test.go | 2 ++ pkg/reconciler/trigger/trigger_test.go | 14 ++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/pkg/reconciler/brokercell/brokercell_test.go b/pkg/reconciler/brokercell/brokercell_test.go index 23e873daf6..d166a1cbab 100644 --- a/pkg/reconciler/brokercell/brokercell_test.go +++ b/pkg/reconciler/brokercell/brokercell_test.go @@ -870,6 +870,7 @@ func TestAllCases(t *testing.T) { Objects: []runtime.Object{NewBrokerCell(brokerCellName, testNS, WithBrokerCellAnnotations(creatorAnnotation), WithBrokerCellSetDefaults, + WithInitBrokerCellConditions, )}, WithReactors: []clientgotesting.ReactionFunc{InduceFailure("delete", "brokercells")}, WantDeletes: []clientgotesting.DeleteActionImpl{ @@ -891,6 +892,7 @@ func TestAllCases(t *testing.T) { Objects: []runtime.Object{NewBrokerCell(brokerCellName, testNS, WithBrokerCellAnnotations(creatorAnnotation), WithBrokerCellSetDefaults, + WithInitBrokerCellConditions, )}, WantDeletes: []clientgotesting.DeleteActionImpl{ { diff --git a/pkg/reconciler/trigger/trigger_test.go b/pkg/reconciler/trigger/trigger_test.go index aeb67fa123..368a49f1e4 100644 --- a/pkg/reconciler/trigger/trigger_test.go +++ b/pkg/reconciler/trigger/trigger_test.go @@ -148,7 +148,9 @@ func TestAllCasesTrigger(t *testing.T) { NewTrigger(triggerName, testNS, brokerName, WithTriggerUID(testUID), WithTriggerFinalizers(finalizerName), - WithTriggerSetDefaults), + WithTriggerSetDefaults, + WithInitTriggerConditions, + ), }, WantEvents: []string{ Eventf(corev1.EventTypeNormal, "TopicDeleted", `Deleted PubSub topic "cre-tgr_testnamespace_test-trigger_abc123"`), @@ -172,7 +174,9 @@ func TestAllCasesTrigger(t *testing.T) { NewTrigger(triggerName, testNS, brokerName, WithTriggerUID(testUID), WithTriggerFinalizers(finalizerName), - WithTriggerSetDefaults), + WithTriggerSetDefaults, + WithInitTriggerConditions, + ), }, WantEvents: []string{ Eventf(corev1.EventTypeNormal, "TopicDeleted", `Deleted PubSub topic "cre-tgr_testnamespace_test-trigger_abc123"`), @@ -196,7 +200,9 @@ func TestAllCasesTrigger(t *testing.T) { NewTrigger(triggerName, testNS, brokerName, WithTriggerUID(testUID), WithTriggerFinalizers(finalizerName), - WithTriggerSetDefaults), + WithTriggerSetDefaults, + WithInitTriggerConditions, + ), }, WantEvents: []string{ Eventf(corev1.EventTypeNormal, "TopicDeleted", `Deleted PubSub topic "cre-tgr_testnamespace_test-trigger_abc123"`), @@ -260,7 +266,7 @@ func TestAllCasesTrigger(t *testing.T) { WithBrokerClass(brokerv1beta1.BrokerClass), WithInitBrokerConditions, WithBrokerReady("url"), - WithBrokerSetDefaults,), + WithBrokerSetDefaults, ), NewTrigger(triggerName, testNS, brokerName, WithTriggerUID(testUID), WithTriggerSubscriberRef(subscriberGVK, subscriberName, testNS), From 6b57a470eecf7e416ccbfa37c745be4f364ca975 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Tue, 23 Jun 2020 20:44:04 -0700 Subject: [PATCH 24/28] leaving e2e tests images with cev1 for now.. that change should be done in a follow up --- pkg/kncloudevents/good_client.go | 48 ++++++++++++++++++ test/test_images/auditlogs_receiver/main.go | 32 ++++++------ test/test_images/auditlogs_target/main.go | 4 +- .../internal/knockdown/knockdown.go | 2 +- test/test_images/pubsub_receiver/main.go | 27 +++++----- test/test_images/pubsub_target/main.go | 2 +- test/test_images/receiver/main.go | 28 ++++++----- test/test_images/scheduler_receiver/main.go | 29 ++++++----- test/test_images/scheduler_target/main.go | 4 +- test/test_images/sender/main.go | 49 +++++++++---------- test/test_images/storage_receiver/main.go | 30 +++++++----- test/test_images/storage_target/main.go | 2 +- test/test_images/target/main.go | 2 +- 13 files changed, 162 insertions(+), 97 deletions(-) create mode 100644 pkg/kncloudevents/good_client.go diff --git a/pkg/kncloudevents/good_client.go b/pkg/kncloudevents/good_client.go new file mode 100644 index 0000000000..4ab016d440 --- /dev/null +++ b/pkg/kncloudevents/good_client.go @@ -0,0 +1,48 @@ +/* +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 kncloudevents + +import ( + cloudevents "github.com/cloudevents/sdk-go" + "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http" +) + +func NewDefaultClient(target ...string) (cloudevents.Client, error) { + tOpts := []http.Option{ + cloudevents.WithBinaryEncoding(), + } + if len(target) > 0 && target[0] != "" { + tOpts = append(tOpts, cloudevents.WithTarget(target[0])) + } + + // Make an http transport for the CloudEvents client. + t, err := cloudevents.NewHTTPTransport(tOpts...) + if err != nil { + return nil, err + } + + // Use the transport to make a new CloudEvents client. + c, err := cloudevents.NewClient(t, + cloudevents.WithUUIDs(), + cloudevents.WithTimeNow(), + ) + + if err != nil { + return nil, err + } + return c, nil +} diff --git a/test/test_images/auditlogs_receiver/main.go b/test/test_images/auditlogs_receiver/main.go index d5470da2ed..cb54e4e7bf 100644 --- a/test/test_images/auditlogs_receiver/main.go +++ b/test/test_images/auditlogs_receiver/main.go @@ -19,10 +19,12 @@ package main import ( "context" "fmt" - cloudevents "github.com/cloudevents/sdk-go/v2" + "log" + "net/http" + + cloudevents "github.com/cloudevents/sdk-go" "github.com/google/knative-gcp/pkg/apis/events/v1beta1" "github.com/google/knative-gcp/test/e2e/lib" - "log" ) type Receiver struct { @@ -42,23 +44,25 @@ func main() { } } -func (r *Receiver) Receive(event cloudevents.Event) (*cloudevents.Event, error) { +func (r *Receiver) Receive(ctx context.Context, event cloudevents.Event, resp *cloudevents.EventResponse) { // Check if the received event is the event sent by CloudAuditLogsSource. // If it is, send back a response CloudEvent. // Print out event received to log fmt.Printf("auditlogs receiver received event\n") fmt.Printf("context of event is: %v\n", event.Context.String()) - if event.Type() != v1beta1.CloudAuditLogsSourceEvent { - return nil, fmt.Errorf("unexpected cloud event type got=%s, want=%s", event.Type(), v1beta1.CloudAuditLogsSourceEvent) + if event.Type() == v1beta1.CloudAuditLogsSourceEvent { + resp.Status = http.StatusAccepted + respEvent := cloudevents.NewEvent(cloudevents.VersionV1) + respEvent.SetID(lib.E2EAuditLogsRespEventID) + respEvent.SetType(lib.E2EAuditLogsRespType) + respEvent.SetSource(event.Source()) + respEvent.SetSubject(event.Subject()) + respEvent.SetData(event.Data) + respEvent.SetDataContentType(event.DataContentType()) + fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) + resp.Event = &respEvent + } else { + resp.Status = http.StatusForbidden } - respEvent := cloudevents.NewEvent(cloudevents.VersionV1) - respEvent.SetID(lib.E2EAuditLogsRespEventID) - respEvent.SetType(lib.E2EAuditLogsRespType) - respEvent.SetSource(event.Source()) - respEvent.SetSubject(event.Subject()) - respEvent.SetData(event.DataContentType(), event.Data) - fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) - return &respEvent, nil - } diff --git a/test/test_images/auditlogs_target/main.go b/test/test_images/auditlogs_target/main.go index 6463023e66..317d0826cd 100644 --- a/test/test_images/auditlogs_target/main.go +++ b/test/test_images/auditlogs_target/main.go @@ -21,7 +21,7 @@ import ( "fmt" "os" - cloudevents "github.com/cloudevents/sdk-go/v2" + cloudevents "github.com/cloudevents/sdk-go" "github.com/google/knative-gcp/test/e2e/lib" "github.com/google/knative-gcp/test/test_images/internal/knockdown" "github.com/kelseyhightower/envconfig" @@ -70,7 +70,7 @@ func (r *auditLogReceiver) Knockdown(event cloudevents.Event) bool { fmt.Printf("event.Context is %s", event.Context.String()) var eventData map[string]interface{} - if err := json.Unmarshal(event.Data(), &eventData); err != nil { + if err := json.Unmarshal(event.Data.([]byte), &eventData); err != nil { fmt.Printf("failed unmarshall event.Data %s.\n", err.Error()) } payload := eventData[protoPayload].(map[string]interface{}) diff --git a/test/test_images/internal/knockdown/knockdown.go b/test/test_images/internal/knockdown/knockdown.go index 1cf5d5f947..48bcbee014 100644 --- a/test/test_images/internal/knockdown/knockdown.go +++ b/test/test_images/internal/knockdown/knockdown.go @@ -24,7 +24,7 @@ import ( "log" "time" - cloudevents "github.com/cloudevents/sdk-go/v2" + cloudevents "github.com/cloudevents/sdk-go" ) // Config is a common envconfig filled struct that includes the common options for knockdown diff --git a/test/test_images/pubsub_receiver/main.go b/test/test_images/pubsub_receiver/main.go index bdb417c3e9..e9eb8a1cac 100644 --- a/test/test_images/pubsub_receiver/main.go +++ b/test/test_images/pubsub_receiver/main.go @@ -20,9 +20,11 @@ import ( "context" "fmt" "log" + "net/http" - cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/knative-gcp/pkg/apis/events/v1beta1" + + cloudevents "github.com/cloudevents/sdk-go" "github.com/google/knative-gcp/test/e2e/lib" ) @@ -43,21 +45,24 @@ func main() { } } -func (r *Receiver) Receive(event cloudevents.Event) (*cloudevents.Event, error) { +func (r *Receiver) Receive(ctx context.Context, event cloudevents.Event, resp *cloudevents.EventResponse) { // Check if the received event is the event sent by CloudPubSubSource. // If it is, send back a response CloudEvent. // Print out event received to log fmt.Printf("pubsub receiver received event\n") fmt.Printf("context of event is: %v\n", event.Context.String()) - if event.Type() != v1beta1.CloudPubSubSourcePublish { - return nil, fmt.Errorf("unexpected cloud event type got=%s, want=%s", event.Type(), v1beta1.CloudPubSubSourcePublish) + if event.Type() == v1beta1.CloudPubSubSourcePublish { + resp.Status = http.StatusAccepted + respEvent := cloudevents.NewEvent(cloudevents.VersionV1) + respEvent.SetID(lib.E2EPubSubRespEventID) + respEvent.SetType(lib.E2EPubSubRespEventType) + respEvent.SetSource(event.Source()) + respEvent.SetDataContentType(event.DataContentType()) + respEvent.SetData(`{"source": "pubsub"}`) + fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) + resp.Event = &respEvent + } else { + resp.Status = http.StatusForbidden } - respEvent := cloudevents.NewEvent(cloudevents.VersionV1) - respEvent.SetID(lib.E2EPubSubRespEventID) - respEvent.SetType(lib.E2EPubSubRespEventType) - respEvent.SetSource(event.Source()) - respEvent.SetData(cloudevents.ApplicationJSON, `{"source": "pubsub"}`) - fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) - return &respEvent, nil } diff --git a/test/test_images/pubsub_target/main.go b/test/test_images/pubsub_target/main.go index f97adc99d0..f50cd6b23e 100644 --- a/test/test_images/pubsub_target/main.go +++ b/test/test_images/pubsub_target/main.go @@ -20,7 +20,7 @@ import ( "fmt" "os" - cloudevents "github.com/cloudevents/sdk-go/v2" + cloudevents "github.com/cloudevents/sdk-go" "github.com/google/knative-gcp/test/e2e/lib" "github.com/google/knative-gcp/test/test_images/internal/knockdown" "github.com/kelseyhightower/envconfig" diff --git a/test/test_images/receiver/main.go b/test/test_images/receiver/main.go index fec8715b0d..c345be8e31 100644 --- a/test/test_images/receiver/main.go +++ b/test/test_images/receiver/main.go @@ -18,10 +18,10 @@ package main import ( "context" - "fmt" "log" + "net/http" - cloudevents "github.com/cloudevents/sdk-go/v2" + cloudevents "github.com/cloudevents/sdk-go" "github.com/google/knative-gcp/test/e2e/lib" ) @@ -42,17 +42,19 @@ func main() { } } -func (r *Receiver) Receive(event cloudevents.Event) (*cloudevents.Event, error) { - // Check if the received event is the dummy event sent by sender pod.&event, nil +func (r *Receiver) Receive(ctx context.Context, event cloudevents.Event, resp *cloudevents.EventResponse) { + // Check if the received event is the dummy event sent by sender pod. // If it is, send back a response CloudEvent. - if event.ID() != lib.E2EDummyEventID { - return nil, fmt.Errorf("unexpected cloud event id got=%s, want=%s", event.ID(), lib.E2EDummyEventID) + if event.ID() == lib.E2EDummyEventID { + resp.Status = http.StatusAccepted + event = cloudevents.NewEvent(cloudevents.VersionV1) + event.SetID(lib.E2EDummyRespEventID) + event.SetType(lib.E2EDummyRespEventType) + event.SetSource(lib.E2EDummyRespEventSource) + event.SetDataContentType(cloudevents.ApplicationJSON) + event.SetData(`{"source": "receiver!"}`) + resp.Event = &event + } else { + resp.Status = http.StatusForbidden } - event = cloudevents.NewEvent(cloudevents.VersionV1) - event.SetID(lib.E2EDummyRespEventID) - event.SetType(lib.E2EDummyRespEventType) - event.SetSource(lib.E2EDummyRespEventSource) - event.SetData(cloudevents.ApplicationJSON, `{"source": "receiver!"}`) - return &event, nil - } diff --git a/test/test_images/scheduler_receiver/main.go b/test/test_images/scheduler_receiver/main.go index 24f848a82c..bce6bcab88 100644 --- a/test/test_images/scheduler_receiver/main.go +++ b/test/test_images/scheduler_receiver/main.go @@ -20,9 +20,11 @@ import ( "context" "fmt" "log" + "net/http" - cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/knative-gcp/pkg/apis/events/v1beta1" + + cloudevents "github.com/cloudevents/sdk-go" "github.com/google/knative-gcp/test/e2e/lib" ) @@ -43,22 +45,25 @@ func main() { } } -func (r *Receiver) Receive(event cloudevents.Event) (*cloudevents.Event, error) { +func (r *Receiver) Receive(ctx context.Context, event cloudevents.Event, resp *cloudevents.EventResponse) { // Check if the received event is the event sent by CloudSchedulerSource. // If it is, send back a response CloudEvent. // Print out event received to log fmt.Printf("scheduler receiver received event\n") fmt.Printf("context of event is: %v\n", event.Context.String()) - if event.Type() != v1beta1.CloudSchedulerSourceExecute { - return nil, fmt.Errorf("unexpected cloud event type got=%s, want=%s", event.Type(), v1beta1.CloudSchedulerSourceExecute) + if event.Type() == v1beta1.CloudSchedulerSourceExecute { + resp.Status = http.StatusAccepted + respEvent := cloudevents.NewEvent(cloudevents.VersionV1) + respEvent.SetID(lib.E2ESchedulerRespEventID) + respEvent.SetType(lib.E2ESchedulerRespType) + respEvent.SetSource(event.Source()) + respEvent.SetSubject(event.Subject()) + respEvent.SetData(event.Data) + respEvent.SetDataContentType(event.DataContentType()) + fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) + resp.Event = &respEvent + } else { + resp.Status = http.StatusForbidden } - respEvent := cloudevents.NewEvent(cloudevents.VersionV1) - respEvent.SetID(lib.E2ESchedulerRespEventID) - respEvent.SetType(lib.E2ESchedulerRespType) - respEvent.SetSource(event.Source()) - respEvent.SetSubject(event.Subject()) - respEvent.SetData(event.DataContentType(), event.Data) - fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) - return &respEvent, nil } diff --git a/test/test_images/scheduler_target/main.go b/test/test_images/scheduler_target/main.go index 4a6d4ccdab..ca13956238 100644 --- a/test/test_images/scheduler_target/main.go +++ b/test/test_images/scheduler_target/main.go @@ -5,7 +5,7 @@ import ( "os" "strings" - cloudevents "github.com/cloudevents/sdk-go/v2" + cloudevents "github.com/cloudevents/sdk-go" "github.com/google/knative-gcp/test/e2e/lib" "github.com/google/knative-gcp/test/test_images/internal/knockdown" "github.com/kelseyhightower/envconfig" @@ -55,7 +55,7 @@ func (r *schedulerReceiver) Knockdown(event cloudevents.Event) bool { } // Check data - data := string(event.Data()) + data := string(event.Data.([]uint8)) if data != r.Data { incorrectAttributes[lib.EventData] = lib.PropPair{Expected: r.Data, Received: data} } diff --git a/test/test_images/sender/main.go b/test/test_images/sender/main.go index 3daca2a6aa..7baa0a504a 100644 --- a/test/test_images/sender/main.go +++ b/test/test_images/sender/main.go @@ -21,9 +21,11 @@ import ( "encoding/json" "fmt" "io/ioutil" + "net/http" "os" - cloudevents "github.com/cloudevents/sdk-go/v2" + cloudevents "github.com/cloudevents/sdk-go" + "github.com/google/knative-gcp/pkg/kncloudevents" "github.com/google/knative-gcp/test/e2e/lib" "go.opencensus.io/trace" ) @@ -35,40 +37,25 @@ const ( func main() { brokerURL := os.Getenv(brokerURLEnvVar) - t, err := cloudevents.NewHTTP(cloudevents.WithTarget(brokerURL)) + ceClient, err := kncloudevents.NewDefaultClient(brokerURL) if err != nil { - fmt.Printf("Unable to create transport: %v ", err) - os.Exit(1) - } - - c, err := cloudevents.NewClient(t, - cloudevents.WithTimeNow(), - cloudevents.WithUUIDs(), - ) - - if err != nil { - fmt.Printf("Unable to create client: %v", err) - os.Exit(1) + fmt.Printf("Unable to create ceClient: %s ", err) } ctx, span := trace.StartSpan(context.Background(), "sender", trace.WithSampler(trace.AlwaysSample())) defer span.End() - event := cloudevents.NewEvent(cloudevents.VersionV1) - event.SetID(lib.E2EDummyEventID) - event.SetType(lib.E2EDummyEventType) - event.SetSource(lib.E2EDummyEventSource) - event.SetDataContentType(cloudevents.ApplicationJSON) - event.SetData(cloudevents.ApplicationJSON, `{"source": "sender!"}`) - + ctx, _, err = ceClient.Send(ctx, dummyCloudEvent()) + rtctx := cloudevents.HTTPTransportContextFrom(ctx) + if err != nil { + fmt.Print(err) + } var success bool - if res := c.Send(ctx, event); !cloudevents.IsACK(res) { - fmt.Printf("Failed to send event to %s: %s\n", brokerURL, res.Error()) - success = false - } else { + if rtctx.StatusCode >= http.StatusOK && rtctx.StatusCode < http.StatusBadRequest { success = true + } else { + success = false } - if err := writeTerminationMessage(map[string]interface{}{ "success": success, "traceid": span.SpanContext().TraceID.String(), @@ -77,6 +64,16 @@ func main() { } } +func dummyCloudEvent() cloudevents.Event { + event := cloudevents.NewEvent(cloudevents.VersionV1) + event.SetID(lib.E2EDummyEventID) + event.SetType(lib.E2EDummyEventType) + event.SetSource(lib.E2EDummyEventSource) + event.SetDataContentType(cloudevents.ApplicationJSON) + event.SetData(`{"source": "sender!"}`) + return event +} + func writeTerminationMessage(result interface{}) error { b, err := json.Marshal(result) if err != nil { diff --git a/test/test_images/storage_receiver/main.go b/test/test_images/storage_receiver/main.go index b99b397fef..44a06bd8ca 100644 --- a/test/test_images/storage_receiver/main.go +++ b/test/test_images/storage_receiver/main.go @@ -19,10 +19,12 @@ package main import ( "context" "fmt" - cloudevents "github.com/cloudevents/sdk-go/v2" + "log" + "net/http" + + cloudevents "github.com/cloudevents/sdk-go" "github.com/google/knative-gcp/pkg/apis/events/v1beta1" "github.com/google/knative-gcp/test/e2e/lib" - "log" ) type Receiver struct { @@ -42,22 +44,24 @@ func main() { } } -func (r *Receiver) Receive(event cloudevents.Event) (*cloudevents.Event, error) { +func (r *Receiver) Receive(ctx context.Context, event cloudevents.Event, resp *cloudevents.EventResponse) { // Check if the received event is the event sent by CloudStorageSource. // If it is, send back a response CloudEvent. // Print out event received to log fmt.Printf("storage receiver received event\n") fmt.Printf("context of event is: %v\n", event.Context.String()) - if event.Type() != v1beta1.CloudStorageSourceFinalize { - return nil, fmt.Errorf("unexpected cloud event type got=%s, want=%s", event.Type(), v1beta1.CloudStorageSourceFinalize) + if event.Type() == v1beta1.CloudStorageSourceFinalize { + resp.Status = http.StatusAccepted + respEvent := cloudevents.NewEvent(cloudevents.VersionV1) + respEvent.SetID(lib.E2EStorageRespEventID) + respEvent.SetType(lib.E2EStorageRespEventType) + respEvent.SetSource(event.Source()) + respEvent.SetSubject(event.Subject()) + respEvent.SetDataContentType(event.DataContentType()) + fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) + resp.Event = &respEvent + } else { + resp.Status = http.StatusForbidden } - respEvent := cloudevents.NewEvent(cloudevents.VersionV1) - respEvent.SetID(lib.E2EStorageRespEventID) - respEvent.SetType(lib.E2EStorageRespEventType) - respEvent.SetSource(event.Source()) - respEvent.SetSubject(event.Subject()) - respEvent.SetData(cloudevents.ApplicationJSON, `{"source": "storage"}`) - fmt.Printf("context of respEvent is: %v\n", respEvent.Context.String()) - return &respEvent, nil } diff --git a/test/test_images/storage_target/main.go b/test/test_images/storage_target/main.go index e3f2df843d..62f0701feb 100644 --- a/test/test_images/storage_target/main.go +++ b/test/test_images/storage_target/main.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - cloudevents "github.com/cloudevents/sdk-go/v2" + cloudevents "github.com/cloudevents/sdk-go" "github.com/google/knative-gcp/test/e2e/lib" "github.com/google/knative-gcp/test/test_images/internal/knockdown" "github.com/kelseyhightower/envconfig" diff --git a/test/test_images/target/main.go b/test/test_images/target/main.go index 5cde315960..1c0f1b824a 100644 --- a/test/test_images/target/main.go +++ b/test/test_images/target/main.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - cloudevents "github.com/cloudevents/sdk-go/v2" + cloudevents "github.com/cloudevents/sdk-go" "github.com/google/knative-gcp/test/e2e/lib" "github.com/google/knative-gcp/test/test_images/internal/knockdown" "github.com/kelseyhightower/envconfig" From 9ef7b161a92859185239eac263c7cf057c85d0e8 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Tue, 23 Jun 2020 20:44:35 -0700 Subject: [PATCH 25/28] updating deps --- .../github.com/cloudevents/sdk-go/LICENSE | 201 ++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/LICENSE diff --git a/third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/LICENSE b/third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/third_party/VENDOR-LICENSE/github.com/cloudevents/sdk-go/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. From cd2b40cad8660b14a4932bc8fed2054e9a77fa6d Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Wed, 24 Jun 2020 12:08:10 -0700 Subject: [PATCH 26/28] sync start --- cmd/pubsub/receive_adapter/main.go | 14 +++++--------- pkg/pubsub/adapter/adapter.go | 6 ++---- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/cmd/pubsub/receive_adapter/main.go b/cmd/pubsub/receive_adapter/main.go index c3cbea2cbc..213f21b043 100644 --- a/cmd/pubsub/receive_adapter/main.go +++ b/cmd/pubsub/receive_adapter/main.go @@ -187,19 +187,15 @@ func main() { } logger.Info("Starting Receive Adapter.", zap.String("projectID", projectID), zap.String("topicID", env.Topic), zap.String("subscriptionID", env.Subscription)) - adapter.Start(ctx, func(err error) { - if err != nil { - logger.Error("Adapter has stopped with error", zap.String("projectID", projectID), zap.String("topicID", env.Topic), zap.String("subscriptionID", env.Subscription), zap.Error(err)) - } else { - logger.Error("Adapter has stopped", zap.String("projectID", projectID), zap.String("topicID", env.Topic), zap.String("subscriptionID", env.Subscription), zap.Error(err)) - } - }) + if err := adapter.Start(ctx); err != nil { + logger.Error("Adapter has stopped with error", zap.String("projectID", projectID), zap.String("topicID", env.Topic), zap.String("subscriptionID", env.Subscription), zap.Error(err)) + } else { + logger.Error("Adapter has stopped", zap.String("projectID", projectID), zap.String("topicID", env.Topic), zap.String("subscriptionID", env.Subscription), zap.Error(err)) + } - <-ctx.Done() // Wait a grace period for the handlers to shutdown. time.Sleep(30 * time.Second) logger.Info("Exiting...") - } func flush(logger *zap.Logger) { diff --git a/pkg/pubsub/adapter/adapter.go b/pkg/pubsub/adapter/adapter.go index 9dc2903ccf..c48d1b715f 100644 --- a/pkg/pubsub/adapter/adapter.go +++ b/pkg/pubsub/adapter/adapter.go @@ -115,7 +115,7 @@ func NewAdapter( } } -func (a *Adapter) Start(ctx context.Context, done func(error)) { +func (a *Adapter) Start(ctx context.Context) error { ctx, a.cancel = context.WithCancel(ctx) // Augment context so that we can use it to create CE attributes. @@ -123,9 +123,7 @@ func (a *Adapter) Start(ctx context.Context, done func(error)) { ctx = WithTopicKey(ctx, a.args.TopicID) ctx = WithSubscriptionKey(ctx, a.subscription.ID()) - go func() { - done(a.subscription.Receive(ctx, a.receive)) - }() + return a.subscription.Receive(ctx, a.receive) } // Stop stops the adapter. From 5f9afd0beaf6dee9b7778d07e0dcdbd18f32f17b Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Wed, 24 Jun 2020 12:35:29 -0700 Subject: [PATCH 27/28] nits after code review --- pkg/pubsub/adapter/converters/build_test.go | 23 ++--------- pkg/pubsub/adapter/converters/storage_test.go | 39 ++----------------- pkg/pubsub/adapter/stats_reporter_test.go | 5 ++- 3 files changed, 10 insertions(+), 57 deletions(-) diff --git a/pkg/pubsub/adapter/converters/build_test.go b/pkg/pubsub/adapter/converters/build_test.go index 7944c40c7c..8a4905ab03 100644 --- a/pkg/pubsub/adapter/converters/build_test.go +++ b/pkg/pubsub/adapter/converters/build_test.go @@ -21,7 +21,6 @@ import ( "time" "cloud.google.com/go/pubsub" - cev2 "github.com/cloudevents/sdk-go/v2" "github.com/google/knative-gcp/pkg/apis/events/v1beta1" . "github.com/google/knative-gcp/pkg/pubsub/adapter/context" ) @@ -38,10 +37,9 @@ var ( func TestConvertCloudBuild(t *testing.T) { tests := []struct { - name string - message *pubsub.Message - wantEventFn func() *cev2.Event - wantErr bool + name string + message *pubsub.Message + wantErr bool }{{ name: "valid event", message: &pubsub.Message{ @@ -55,9 +53,6 @@ func TestConvertCloudBuild(t *testing.T) { "attribute2": "value2", }, }, - wantEventFn: func() *cev2.Event { - return buildCloudEvent(buildID, buildStatus) - }, }, { name: "no buildId attributes", @@ -120,15 +115,3 @@ func TestConvertCloudBuild(t *testing.T) { }) } } - -func buildCloudEvent(buildID, buildStatus string) *cev2.Event { - e := cev2.NewEvent(cev2.VersionV1) - e.SetID("id") - e.SetTime(buildPublishTime) - e.SetSource(v1beta1.CloudBuildSourceEventSource("testproject", buildID)) - e.SetSubject(buildStatus) - e.SetData(cev2.ApplicationJSON, []byte("test data")) - e.SetType(v1beta1.CloudBuildSourceEvent) - e.SetDataSchema(buildSchemaUrl) - return &e -} diff --git a/pkg/pubsub/adapter/converters/storage_test.go b/pkg/pubsub/adapter/converters/storage_test.go index 4128dc5600..5ead70ac0e 100644 --- a/pkg/pubsub/adapter/converters/storage_test.go +++ b/pkg/pubsub/adapter/converters/storage_test.go @@ -23,8 +23,6 @@ import ( "cloud.google.com/go/pubsub" "github.com/google/knative-gcp/pkg/apis/events/v1beta1" - - cev2 "github.com/cloudevents/sdk-go/v2" ) const ( @@ -40,18 +38,14 @@ var ( func TestConvertCloudStorageSource(t *testing.T) { tests := []struct { - name string - message *pubsub.Message - wantEventFn func() *cev2.Event - wantErr bool + name string + message *pubsub.Message + wantErr bool }{{ name: "no attributes", message: &pubsub.Message{ Data: []byte("test data"), }, - wantEventFn: func() *cev2.Event { - return storageCloudEvent() - }, wantErr: true, }, { name: "no bucketId attribute", @@ -63,9 +57,6 @@ func TestConvertCloudStorageSource(t *testing.T) { "attribute2": "value2", }, }, - wantEventFn: func() *cev2.Event { - return storageCloudEvent() - }, wantErr: true, }, { name: "no eventType attribute", @@ -76,9 +67,6 @@ func TestConvertCloudStorageSource(t *testing.T) { "objectId": objectId, }, }, - wantEventFn: func() *cev2.Event { - return storageCloudEvent() - }, wantErr: true, }, { name: "unkown eventType attribute", @@ -90,9 +78,6 @@ func TestConvertCloudStorageSource(t *testing.T) { "objectId": objectId, }, }, - wantEventFn: func() *cev2.Event { - return storageCloudEvent() - }, wantErr: true, }, { name: "no objectId attribute", @@ -103,9 +88,6 @@ func TestConvertCloudStorageSource(t *testing.T) { "eventType": eventType, }, }, - wantEventFn: func() *cev2.Event { - return storageCloudEvent() - }, wantErr: true, }, { name: "valid message", @@ -119,9 +101,6 @@ func TestConvertCloudStorageSource(t *testing.T) { "objectId": objectId, }, }, - wantEventFn: func() *cev2.Event { - return storageCloudEvent() - }, }} for _, test := range tests { @@ -155,15 +134,3 @@ func TestConvertCloudStorageSource(t *testing.T) { }) } } - -func storageCloudEvent() *cev2.Event { - e := cev2.NewEvent(cev2.VersionV1) - e.SetID("id") - e.SetTime(storagePublishTime) - e.SetData(cev2.ApplicationJSON, []byte("test data")) - e.SetDataSchema(storageSchemaUrl) - e.SetSource(v1beta1.CloudStorageSourceEventSource(bucket)) - e.SetType(v1beta1.CloudStorageSourceFinalize) - e.SetSubject(objectId) - return &e -} diff --git a/pkg/pubsub/adapter/stats_reporter_test.go b/pkg/pubsub/adapter/stats_reporter_test.go index 97edb19424..f2773f3842 100644 --- a/pkg/pubsub/adapter/stats_reporter_test.go +++ b/pkg/pubsub/adapter/stats_reporter_test.go @@ -32,7 +32,10 @@ func TestStatsReporter(t *testing.T) { EventSource: "unit-test", } - r, _ := NewStatsReporter("testobject", "testns", "testresourcegroup") + r, err := NewStatsReporter("testobject", "testns", "testresourcegroup") + if err != nil { + t.Fatalf("Error creating reporter: %v", err) + } wantTags := map[string]string{ metricskey.LabelNamespaceName: "testns", From 014802aae6fc2fc72c66139748dc851984b6b793 Mon Sep 17 00:00:00 2001 From: Nacho Cano Date: Wed, 24 Jun 2020 12:44:41 -0700 Subject: [PATCH 28/28] no need to delete attributes --- pkg/pubsub/adapter/converters/scheduler.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pkg/pubsub/adapter/converters/scheduler.go b/pkg/pubsub/adapter/converters/scheduler.go index 124ec1ea02..eb81c6c95f 100644 --- a/pkg/pubsub/adapter/converters/scheduler.go +++ b/pkg/pubsub/adapter/converters/scheduler.go @@ -37,15 +37,11 @@ func convertCloudScheduler(ctx context.Context, msg *pubsub.Message) (*cev2.Even // We added this attributes so that we could identify the scheduler. // We should remove them here. jobName, ok := msg.Attributes[v1beta1.CloudSchedulerSourceJobName] - if ok { - delete(msg.Attributes, v1beta1.CloudSchedulerSourceJobName) - } else { + if !ok { return nil, errors.New("received event did not have jobName") } schedulerName, ok := msg.Attributes[v1beta1.CloudSchedulerSourceName] - if ok { - delete(msg.Attributes, v1beta1.CloudSchedulerSourceName) - } else { + if !ok { return nil, errors.New("received event did not have schedulerName") }