From ea605adce503ad97cb3a6e9eacb693d3ef079ab9 Mon Sep 17 00:00:00 2001 From: David Simansky Date: Tue, 3 Oct 2023 09:48:59 +0200 Subject: [PATCH] [release-v1.10] Add kn-plugin-source-kafka v1.10.0 (#271) --- go.mod | 6 + go.sum | 6 + openshift/release/kn.yaml | 25 + pkg/kn/root/plugin_register.go | 26 + .../knative.dev/client-pkg/pkg/LICENSE | 201 +++ .../knative.dev/eventing-kafka/pkg/LICENSE | 201 +++ .../kn-plugin-source-kafka/LICENSE | 201 +++ .../pkg/api/apitesting/fuzzer/fuzzer.go | 52 + .../pkg/api/apitesting/fuzzer/valuefuzz.go | 86 ++ vendor/knative.dev/client-pkg/LICENSE | 201 +++ .../client-pkg/pkg/config/defaults.go | 37 + .../client-pkg/pkg/dynamic/client.go | 272 ++++ .../client-pkg/pkg/dynamic/client_mock.go | 144 +++ .../client-pkg/pkg/dynamic/fake/fake.go | 44 + .../knative.dev/client-pkg/pkg/dynamic/lib.go | 148 +++ .../client-pkg/pkg/errors/errors.go | 50 + .../client-pkg/pkg/errors/factory.go | 90 ++ .../client-pkg/pkg/errors/knerror.go | 25 + .../client-pkg/pkg/errors/types.go | 22 + .../client-pkg/pkg/eventing/v1/client.go | 524 ++++++++ .../client-pkg/pkg/eventing/v1beta1/client.go | 165 +++ .../pkg/kn-source-pkg/pkg/client/client.go | 51 + .../pkg/commands/source/create.go | 30 + .../pkg/commands/source/delete.go | 30 + .../pkg/commands/source/describe.go | 30 + .../kn-source-pkg/pkg/commands/source/list.go | 30 + .../pkg/commands/source/source.go | 30 + .../pkg/commands/source/update.go | 30 + .../pkg/kn-source-pkg/pkg/core/root.go | 91 ++ .../pkg/factories/boilerplate.go | 52 + .../pkg/factories/command_factory.go | 56 + .../pkg/factories/flags_factory.go | 68 + .../pkg/factories/kn_source_factory.go | 49 + .../pkg/factories/rune_factory.go | 133 ++ .../pkg/kn-source-pkg/pkg/types/interfaces.go | 88 ++ .../pkg/kn-source-pkg/pkg/types/structs.go | 37 + .../types/typesfakes/fake_command_factory.go | 493 ++++++++ .../types/typesfakes/fake_flags_factory.go | 428 +++++++ .../types/typesfakes/fake_kn_source_client.go | 233 ++++ .../typesfakes/fake_kn_source_factory.go | 244 ++++ .../pkg/types/typesfakes/fake_run_efactory.go | 505 ++++++++ .../client-pkg/pkg/kn/commands/describe.go | 222 ++++ .../pkg/kn/commands/flags/listprint.go | 102 ++ .../client-pkg/pkg/kn/commands/flags/sink.go | 179 +++ .../pkg/kn/commands/human_readable_flags.go | 121 ++ .../client-pkg/pkg/kn/commands/namespaced.go | 92 ++ .../pkg/kn/commands/testing_helper.go | 98 ++ .../client-pkg/pkg/kn/commands/types.go | 268 ++++ .../client-pkg/pkg/kn/config/config.go | 283 +++++ .../client-pkg/pkg/kn/config/types.go | 88 ++ .../client-pkg/pkg/kn/flags/bool.go | 126 ++ .../client-pkg/pkg/kn/flags/podspec_helper.go | 1094 +++++++++++++++++ .../client-pkg/pkg/kn/plugin/types.go | 30 + .../pkg/messaging/v1/channels_client.go | 165 +++ .../pkg/messaging/v1/channels_client_mock.go | 108 ++ .../client-pkg/pkg/messaging/v1/client.go | 71 ++ .../pkg/messaging/v1/subscriptions_client.go | 235 ++++ .../messaging/v1/subscriptions_client_mock.go | 127 ++ .../client-pkg/pkg/printers/interface.go | 44 + .../client-pkg/pkg/printers/prefixwriter.go | 126 ++ .../client-pkg/pkg/printers/tablegenerator.go | 147 +++ .../client-pkg/pkg/printers/tableprinter.go | 117 ++ .../client-pkg/pkg/printers/tabwriter.go | 36 + .../client-pkg/pkg/serving/config_changes.go | 240 ++++ .../pkg/serving/revision_template.go | 130 ++ .../client-pkg/pkg/serving/v1/apply.go | 268 ++++ .../client-pkg/pkg/serving/v1/client.go | 581 +++++++++ .../client-pkg/pkg/serving/v1/gitops.go | 220 ++++ .../client-pkg/pkg/serving/v1alpha1/client.go | 214 ++++ .../pkg/sources/v1/apiserver_client.go | 218 ++++ .../pkg/sources/v1/apiserver_client_mock.go | 120 ++ .../pkg/sources/v1/binding_client.go | 277 +++++ .../pkg/sources/v1/binding_client_mock.go | 120 ++ .../client-pkg/pkg/sources/v1/client.go | 63 + .../pkg/sources/v1/container_client.go | 215 ++++ .../pkg/sources/v1/container_client_mock.go | 127 ++ .../client-pkg/pkg/sources/v1beta2/client.go | 47 + .../pkg/sources/v1beta2/ping_client.go | 249 ++++ .../pkg/sources/v1beta2/ping_client_mock.go | 122 ++ .../client-pkg/pkg/util/compare.go | 85 ++ .../client-pkg/pkg/util/corev1_helper.go | 88 ++ .../pkg/util/logging_http_transport.go | 84 ++ .../client-pkg/pkg/util/mock/mock_helper.go | 131 ++ .../client-pkg/pkg/util/orderedmap.go | 147 +++ .../client-pkg/pkg/util/parsing_helper.go | 202 +++ .../client-pkg/pkg/util/schema_handling.go | 44 + .../client-pkg/pkg/util/unstructured.go | 66 + .../client-pkg/pkg/wait/poll_watcher.go | 189 +++ .../client-pkg/pkg/wait/test_wait_helper.go | 87 ++ .../client-pkg/pkg/wait/wait_for_ready.go | 312 +++++ vendor/knative.dev/eventing-kafka/LICENSE | 201 +++ .../pkg/apis/bindings/register.go | 33 + .../pkg/apis/bindings/v1beta1/doc.go | 22 + .../pkg/apis/bindings/v1beta1/fuzzer.go | 45 + .../apis/bindings/v1beta1/kafka_conversion.go | 44 + .../apis/bindings/v1beta1/kafka_defaults.go | 29 + .../apis/bindings/v1beta1/kafka_lifecycle.go | 225 ++++ .../pkg/apis/bindings/v1beta1/kafka_types.go | 128 ++ .../apis/bindings/v1beta1/kafka_validation.go | 28 + .../pkg/apis/bindings/v1beta1/register.go | 60 + .../bindings/v1beta1/zz_generated.deepcopy.go | 222 ++++ .../pkg/apis/sources/config/doc.go | 21 + .../pkg/apis/sources/config/kafka_defaults.go | 143 +++ .../pkg/apis/sources/config/store.go | 97 ++ .../pkg/apis/sources/v1beta1/doc.go | 22 + .../pkg/apis/sources/v1beta1/fuzzer.go | 45 + .../apis/sources/v1beta1/kafka_conversion.go | 34 + .../apis/sources/v1beta1/kafka_defaults.go | 74 ++ .../apis/sources/v1beta1/kafka_lifecycle.go | 163 +++ .../sources/v1beta1/kafka_lifecycle_mt.go | 39 + .../apis/sources/v1beta1/kafka_scheduling.go | 52 + .../pkg/apis/sources/v1beta1/kafka_types.go | 154 +++ .../apis/sources/v1beta1/kafka_validation.go | 81 ++ .../pkg/apis/sources/v1beta1/register.go | 59 + .../sources/v1beta1/zz_generated.deepcopy.go | 133 ++ .../client/clientset/versioned/scheme/doc.go | 20 + .../clientset/versioned/scheme/register.go | 58 + .../versioned/typed/sources/v1beta1/doc.go | 20 + .../typed/sources/v1beta1/fake/doc.go | 20 + .../sources/v1beta1/fake/fake_kafkasource.go | 154 +++ .../v1beta1/fake/fake_sources_client.go | 40 + .../sources/v1beta1/generated_expansion.go | 21 + .../typed/sources/v1beta1/kafkasource.go | 212 ++++ .../typed/sources/v1beta1/sources_client.go | 107 ++ .../eventing/pkg/apis/duck/v1alpha1/doc.go | 19 + .../pkg/apis/duck/v1alpha1/placement_types.go | 86 ++ .../pkg/apis/duck/v1alpha1/register.go | 53 + .../duck/v1alpha1/zz_generated.deepcopy.go | 145 +++ .../kn-plugin-source-kafka/LICENSE | 201 +++ .../pkg/client/client.go | 192 +++ .../pkg/client/client_fake.go | 47 + .../pkg/factories/boilerplate.go | 79 ++ .../pkg/factories/command_factory.go | 96 ++ .../pkg/factories/flags_factory.go | 79 ++ .../pkg/factories/rune_factory.go | 371 ++++++ .../pkg/factories/source_factory.go | 84 ++ .../kn-plugin-source-kafka/pkg/root/root.go | 33 + .../pkg/types/interfaces.go | 62 + .../pkg/types/structs.go | 40 + .../kn-plugin-source-kafka/plugin/plugin.go | 60 + .../apis/duck/v1alpha1/addressable_types.go | 174 +++ .../pkg/apis/duck/v1alpha1/binding_types.go | 92 ++ .../knative.dev/pkg/apis/duck/v1alpha1/doc.go | 23 + .../duck/v1alpha1/legacy_targetable_types.go | 96 ++ .../pkg/apis/duck/v1alpha1/register.go | 59 + .../duck/v1alpha1/retired_targetable_types.go | 100 ++ .../duck/v1alpha1/zz_generated.deepcopy.go | 381 ++++++ .../pkg/apis/testing/fuzzer/fuzzer.go | 103 ++ .../webhook/resourcesemantics/interface.go | 50 + vendor/modules.txt | 50 + 150 files changed, 19340 insertions(+) create mode 100644 openshift/release/kn.yaml create mode 100644 pkg/kn/root/plugin_register.go create mode 100644 third_party/VENDOR-LICENSE/knative.dev/client-pkg/pkg/LICENSE create mode 100644 third_party/VENDOR-LICENSE/knative.dev/eventing-kafka/pkg/LICENSE create mode 100644 third_party/VENDOR-LICENSE/knative.dev/kn-plugin-source-kafka/LICENSE create mode 100644 vendor/k8s.io/apimachinery/pkg/api/apitesting/fuzzer/fuzzer.go create mode 100644 vendor/k8s.io/apimachinery/pkg/api/apitesting/fuzzer/valuefuzz.go create mode 100644 vendor/knative.dev/client-pkg/LICENSE create mode 100644 vendor/knative.dev/client-pkg/pkg/config/defaults.go create mode 100644 vendor/knative.dev/client-pkg/pkg/dynamic/client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/dynamic/client_mock.go create mode 100644 vendor/knative.dev/client-pkg/pkg/dynamic/fake/fake.go create mode 100644 vendor/knative.dev/client-pkg/pkg/dynamic/lib.go create mode 100644 vendor/knative.dev/client-pkg/pkg/errors/errors.go create mode 100644 vendor/knative.dev/client-pkg/pkg/errors/factory.go create mode 100644 vendor/knative.dev/client-pkg/pkg/errors/knerror.go create mode 100644 vendor/knative.dev/client-pkg/pkg/errors/types.go create mode 100644 vendor/knative.dev/client-pkg/pkg/eventing/v1/client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/eventing/v1beta1/client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/client/client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/create.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/delete.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/describe.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/list.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/source.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/update.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/core/root.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/boilerplate.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/command_factory.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/flags_factory.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/kn_source_factory.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/rune_factory.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/interfaces.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/structs.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_command_factory.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_flags_factory.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_kn_source_client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_kn_source_factory.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_run_efactory.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn/commands/describe.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn/commands/flags/listprint.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn/commands/flags/sink.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn/commands/human_readable_flags.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn/commands/namespaced.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn/commands/testing_helper.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn/commands/types.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn/config/config.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn/config/types.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn/flags/bool.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn/flags/podspec_helper.go create mode 100644 vendor/knative.dev/client-pkg/pkg/kn/plugin/types.go create mode 100644 vendor/knative.dev/client-pkg/pkg/messaging/v1/channels_client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/messaging/v1/channels_client_mock.go create mode 100644 vendor/knative.dev/client-pkg/pkg/messaging/v1/client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/messaging/v1/subscriptions_client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/messaging/v1/subscriptions_client_mock.go create mode 100644 vendor/knative.dev/client-pkg/pkg/printers/interface.go create mode 100644 vendor/knative.dev/client-pkg/pkg/printers/prefixwriter.go create mode 100644 vendor/knative.dev/client-pkg/pkg/printers/tablegenerator.go create mode 100644 vendor/knative.dev/client-pkg/pkg/printers/tableprinter.go create mode 100644 vendor/knative.dev/client-pkg/pkg/printers/tabwriter.go create mode 100644 vendor/knative.dev/client-pkg/pkg/serving/config_changes.go create mode 100644 vendor/knative.dev/client-pkg/pkg/serving/revision_template.go create mode 100644 vendor/knative.dev/client-pkg/pkg/serving/v1/apply.go create mode 100644 vendor/knative.dev/client-pkg/pkg/serving/v1/client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/serving/v1/gitops.go create mode 100644 vendor/knative.dev/client-pkg/pkg/serving/v1alpha1/client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/sources/v1/apiserver_client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/sources/v1/apiserver_client_mock.go create mode 100644 vendor/knative.dev/client-pkg/pkg/sources/v1/binding_client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/sources/v1/binding_client_mock.go create mode 100644 vendor/knative.dev/client-pkg/pkg/sources/v1/client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/sources/v1/container_client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/sources/v1/container_client_mock.go create mode 100644 vendor/knative.dev/client-pkg/pkg/sources/v1beta2/client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/sources/v1beta2/ping_client.go create mode 100644 vendor/knative.dev/client-pkg/pkg/sources/v1beta2/ping_client_mock.go create mode 100644 vendor/knative.dev/client-pkg/pkg/util/compare.go create mode 100644 vendor/knative.dev/client-pkg/pkg/util/corev1_helper.go create mode 100644 vendor/knative.dev/client-pkg/pkg/util/logging_http_transport.go create mode 100644 vendor/knative.dev/client-pkg/pkg/util/mock/mock_helper.go create mode 100644 vendor/knative.dev/client-pkg/pkg/util/orderedmap.go create mode 100644 vendor/knative.dev/client-pkg/pkg/util/parsing_helper.go create mode 100644 vendor/knative.dev/client-pkg/pkg/util/schema_handling.go create mode 100644 vendor/knative.dev/client-pkg/pkg/util/unstructured.go create mode 100644 vendor/knative.dev/client-pkg/pkg/wait/poll_watcher.go create mode 100644 vendor/knative.dev/client-pkg/pkg/wait/test_wait_helper.go create mode 100644 vendor/knative.dev/client-pkg/pkg/wait/wait_for_ready.go create mode 100644 vendor/knative.dev/eventing-kafka/LICENSE create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/bindings/register.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/doc.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/fuzzer.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_conversion.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_defaults.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_lifecycle.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_types.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_validation.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/register.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/zz_generated.deepcopy.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/sources/config/doc.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/sources/config/kafka_defaults.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/sources/config/store.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/doc.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/fuzzer.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_conversion.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_defaults.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_lifecycle.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_lifecycle_mt.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_scheduling.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_types.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_validation.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/register.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/zz_generated.deepcopy.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/scheme/doc.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/scheme/register.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/doc.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/fake/doc.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/fake/fake_kafkasource.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/fake/fake_sources_client.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/generated_expansion.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/kafkasource.go create mode 100644 vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/sources_client.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/doc.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/placement_types.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/register.go create mode 100644 vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/zz_generated.deepcopy.go create mode 100644 vendor/knative.dev/kn-plugin-source-kafka/LICENSE create mode 100644 vendor/knative.dev/kn-plugin-source-kafka/pkg/client/client.go create mode 100644 vendor/knative.dev/kn-plugin-source-kafka/pkg/client/client_fake.go create mode 100644 vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/boilerplate.go create mode 100644 vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/command_factory.go create mode 100644 vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/flags_factory.go create mode 100644 vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/rune_factory.go create mode 100644 vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/source_factory.go create mode 100644 vendor/knative.dev/kn-plugin-source-kafka/pkg/root/root.go create mode 100644 vendor/knative.dev/kn-plugin-source-kafka/pkg/types/interfaces.go create mode 100644 vendor/knative.dev/kn-plugin-source-kafka/pkg/types/structs.go create mode 100644 vendor/knative.dev/kn-plugin-source-kafka/plugin/plugin.go create mode 100644 vendor/knative.dev/pkg/apis/duck/v1alpha1/addressable_types.go create mode 100644 vendor/knative.dev/pkg/apis/duck/v1alpha1/binding_types.go create mode 100644 vendor/knative.dev/pkg/apis/duck/v1alpha1/doc.go create mode 100644 vendor/knative.dev/pkg/apis/duck/v1alpha1/legacy_targetable_types.go create mode 100644 vendor/knative.dev/pkg/apis/duck/v1alpha1/register.go create mode 100644 vendor/knative.dev/pkg/apis/duck/v1alpha1/retired_targetable_types.go create mode 100644 vendor/knative.dev/pkg/apis/duck/v1alpha1/zz_generated.deepcopy.go create mode 100644 vendor/knative.dev/pkg/apis/testing/fuzzer/fuzzer.go create mode 100644 vendor/knative.dev/pkg/webhook/resourcesemantics/interface.go diff --git a/go.mod b/go.mod index 45737e8591..0d7655ed0c 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,7 @@ require ( k8s.io/code-generator v0.25.4 knative.dev/eventing v0.37.0 knative.dev/hack v0.0.0-20230417170854-f591fea109b3 + knative.dev/kn-plugin-source-kafka v0.37.0 knative.dev/networking v0.0.0-20230419144338-e5d04e805e50 knative.dev/pkg v0.0.0-20230418073056-dfad48eaa5d0 knative.dev/serving v0.37.0 @@ -135,3 +136,8 @@ require ( sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) + +require ( + knative.dev/client-pkg v0.0.0-20230425201444-4f052f9ef2f2 // indirect + knative.dev/eventing-kafka v0.37.0 // indirect +) diff --git a/go.sum b/go.sum index 3933a17961..8fb08a98de 100644 --- a/go.sum +++ b/go.sum @@ -1087,10 +1087,16 @@ k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+O k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2 h1:GfD9OzL11kvZN5iArC6oTS7RTj7oJOIfnislxYlqTj8= k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +knative.dev/client-pkg v0.0.0-20230425201444-4f052f9ef2f2 h1:Xc6zlrbq9X+Qh15xl8iv8Tl/qkknnOv8KwN+HzjDZU8= +knative.dev/client-pkg v0.0.0-20230425201444-4f052f9ef2f2/go.mod h1:oYnznlTBCj/bVEHo5vUSM/VS3oDFNJKDmH5+k1aC9/8= knative.dev/eventing v0.37.0 h1:OtX8B9nvUSTNcbbpoNFDyeGaGU/5+aetj94i6oATpQU= knative.dev/eventing v0.37.0/go.mod h1:62baPXiw5GPpPyV3f0GF64X7tOjc5x9cg64RAh1gjs4= +knative.dev/eventing-kafka v0.37.0 h1:IhFYsO3akqr85nwF6i2yiGFmcLfN7qks/GmAE/MQqRA= +knative.dev/eventing-kafka v0.37.0/go.mod h1:xEEsukYookBRDpJF+H7O+zaPx7cKT0TvqW7apEAIF7E= knative.dev/hack v0.0.0-20230417170854-f591fea109b3 h1:+W4WBOq83tfGXKhtv8OB/uJeYqze3zh69GKiz1ucuqk= knative.dev/hack v0.0.0-20230417170854-f591fea109b3/go.mod h1:yk2OjGDsbEnQjfxdm0/HJKS2WqTLEFg/N6nUs6Rqx3Q= +knative.dev/kn-plugin-source-kafka v0.37.0 h1:pgyVQV32V5eecHWD2sCeRDcAUCfLvHfxDu9USaYCH2Y= +knative.dev/kn-plugin-source-kafka v0.37.0/go.mod h1:vCUUHCV4dyNUvepWa8CTUK2ywaWh4XLxkeEa3MG56U4= knative.dev/networking v0.0.0-20230419144338-e5d04e805e50 h1:X9rPBYr7Vrm075q0iXTr7/0oklkYoyqvlnrUwNzcUhI= knative.dev/networking v0.0.0-20230419144338-e5d04e805e50/go.mod h1:o2MyGpGfU5DoSAWCE2f/jnSC9GjGOplCslbA99yDkGo= knative.dev/pkg v0.0.0-20230418073056-dfad48eaa5d0 h1:EFQcoUo8I4bc+U3y6tR1B3ONYZSHWUdAfI7Vh7dae8g= diff --git a/openshift/release/kn.yaml b/openshift/release/kn.yaml new file mode 100644 index 0000000000..e8ac351032 --- /dev/null +++ b/openshift/release/kn.yaml @@ -0,0 +1,25 @@ +plugins: + - name: kn-plugin-source-kafka + module: knative.dev/kn-plugin-source-kafka + pluginImportPath: knative.dev/kn-plugin-source-kafka/plugin + version: knative-v1.10.0 + # - name: kn-plugin-event + # module: knative.dev/kn-plugin-event + # pluginImportPath: knative.dev/kn-plugin-event/pkg/plugin + # version: v1.10.0 + # replace: + # - module: knative.dev/kn-plugin-event + # moduleSource: github.com/openshift-knative/kn-plugin-event + # version: release-1.10 + # - name: kn-plugin-func + # module: knative.dev/func + # pluginImportPath: knative.dev/func/plugin + # version: v1.11.0 + # replace: + # - module: knative.dev/func + # moduleSource: github.com/openshift-knative/kn-plugin-func + # version: serverless-1.31.0 + # - name: kn-plugin-workflow + # module: github.com/kiegroup/kie-tools/packages/kn-plugin-workflow + # pluginImportPath: github.com/kiegroup/kie-tools/packages/kn-plugin-workflow/plugin + # version: v0.30.3 diff --git a/pkg/kn/root/plugin_register.go b/pkg/kn/root/plugin_register.go new file mode 100644 index 0000000000..8eca53f722 --- /dev/null +++ b/pkg/kn/root/plugin_register.go @@ -0,0 +1,26 @@ +/* +Copyright 2021 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 root + +import ( + // Add #plugins# import here. Don't remove this line, it triggers an automatic replacement. + _ "knative.dev/kn-plugin-source-kafka/plugin" +) + +// RegisterInlinePlugins is an empty function which however forces the +// compiler to run all init() methods of the registered imports +func RegisterInlinePlugins() {} diff --git a/third_party/VENDOR-LICENSE/knative.dev/client-pkg/pkg/LICENSE b/third_party/VENDOR-LICENSE/knative.dev/client-pkg/pkg/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/third_party/VENDOR-LICENSE/knative.dev/client-pkg/pkg/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. diff --git a/third_party/VENDOR-LICENSE/knative.dev/eventing-kafka/pkg/LICENSE b/third_party/VENDOR-LICENSE/knative.dev/eventing-kafka/pkg/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/third_party/VENDOR-LICENSE/knative.dev/eventing-kafka/pkg/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. diff --git a/third_party/VENDOR-LICENSE/knative.dev/kn-plugin-source-kafka/LICENSE b/third_party/VENDOR-LICENSE/knative.dev/kn-plugin-source-kafka/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/third_party/VENDOR-LICENSE/knative.dev/kn-plugin-source-kafka/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. diff --git a/vendor/k8s.io/apimachinery/pkg/api/apitesting/fuzzer/fuzzer.go b/vendor/k8s.io/apimachinery/pkg/api/apitesting/fuzzer/fuzzer.go new file mode 100644 index 0000000000..f528e9f92d --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/api/apitesting/fuzzer/fuzzer.go @@ -0,0 +1,52 @@ +/* +Copyright 2017 The Kubernetes 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 fuzzer + +import ( + "math/rand" + + "github.com/google/gofuzz" + + runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" +) + +// FuzzerFuncs returns a list of func(*SomeType, c fuzz.Continue) functions. +type FuzzerFuncs func(codecs runtimeserializer.CodecFactory) []interface{} + +// FuzzerFor can randomly populate api objects that are destined for version. +func FuzzerFor(funcs FuzzerFuncs, src rand.Source, codecs runtimeserializer.CodecFactory) *fuzz.Fuzzer { + f := fuzz.New().NilChance(.5).NumElements(0, 1) + if src != nil { + f.RandSource(src) + } + f.Funcs(funcs(codecs)...) + return f +} + +// MergeFuzzerFuncs will merge the given funcLists, overriding early funcs with later ones if there first +// argument has the same type. +func MergeFuzzerFuncs(funcs ...FuzzerFuncs) FuzzerFuncs { + return FuzzerFuncs(func(codecs runtimeserializer.CodecFactory) []interface{} { + result := []interface{}{} + for _, f := range funcs { + if f != nil { + result = append(result, f(codecs)...) + } + } + return result + }) +} diff --git a/vendor/k8s.io/apimachinery/pkg/api/apitesting/fuzzer/valuefuzz.go b/vendor/k8s.io/apimachinery/pkg/api/apitesting/fuzzer/valuefuzz.go new file mode 100644 index 0000000000..facff57bba --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/api/apitesting/fuzzer/valuefuzz.go @@ -0,0 +1,86 @@ +/* +Copyright 2017 The Kubernetes 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 fuzzer + +import ( + "reflect" +) + +// ValueFuzz recursively changes all basic type values in an object. Any kind of references will not +// be touch, i.e. the addresses of slices, maps, pointers will stay unchanged. +func ValueFuzz(obj interface{}) { + valueFuzz(reflect.ValueOf(obj)) +} + +func valueFuzz(obj reflect.Value) { + switch obj.Kind() { + case reflect.Array: + for i := 0; i < obj.Len(); i++ { + valueFuzz(obj.Index(i)) + } + case reflect.Slice: + if obj.IsNil() { + // TODO: set non-nil value + } else { + for i := 0; i < obj.Len(); i++ { + valueFuzz(obj.Index(i)) + } + } + case reflect.Interface, reflect.Pointer: + if obj.IsNil() { + // TODO: set non-nil value + } else { + valueFuzz(obj.Elem()) + } + case reflect.Struct: + for i, n := 0, obj.NumField(); i < n; i++ { + valueFuzz(obj.Field(i)) + } + case reflect.Map: + if obj.IsNil() { + // TODO: set non-nil value + } else { + for _, k := range obj.MapKeys() { + // map values are not addressable. We need a copy. + v := obj.MapIndex(k) + copy := reflect.New(v.Type()) + copy.Elem().Set(v) + valueFuzz(copy.Elem()) + obj.SetMapIndex(k, copy.Elem()) + } + // TODO: set some new value + } + case reflect.Func: // ignore, we don't have function types in our API + default: + if !obj.CanSet() { + return + } + switch obj.Kind() { + case reflect.String: + obj.SetString(obj.String() + "x") + case reflect.Bool: + obj.SetBool(!obj.Bool()) + case reflect.Float32, reflect.Float64: + obj.SetFloat(obj.Float()*2.0 + 1.0) + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + obj.SetInt(obj.Int() + 1) + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + obj.SetUint(obj.Uint() + 1) + default: + } + } +} diff --git a/vendor/knative.dev/client-pkg/LICENSE b/vendor/knative.dev/client-pkg/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/vendor/knative.dev/client-pkg/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. diff --git a/vendor/knative.dev/client-pkg/pkg/config/defaults.go b/vendor/knative.dev/client-pkg/pkg/config/defaults.go new file mode 100644 index 0000000000..3f85837e35 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/config/defaults.go @@ -0,0 +1,37 @@ +// Copyright © 2021 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 config + +import ( + "time" + + "k8s.io/apimachinery/pkg/util/wait" +) + +var ( + // DefaultRetry is the default set of rules + // to be followed when retrying for conflicts during + // resource update. Values are the same as + // k8s.io/client-go/util/retry/util.go + // except where commented on + DefaultRetry = wait.Backoff{ + // Start retries with 20ms instead of 10ms + Duration: 20 * time.Millisecond, + // Increase the retry duration by 50% + Factor: 1.5, + Jitter: 0.1, + Steps: 5, + } +) diff --git a/vendor/knative.dev/client-pkg/pkg/dynamic/client.go b/vendor/knative.dev/client-pkg/pkg/dynamic/client.go new file mode 100644 index 0000000000..950abf2ef7 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/dynamic/client.go @@ -0,0 +1,272 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dynamic + +import ( + "context" + "errors" + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/dynamic" + "knative.dev/client-pkg/pkg/util" + "knative.dev/eventing/pkg/apis/messaging" +) + +const ( + crdGroup = "apiextensions.k8s.io" + crdVersion = "v1" + crdKind = "CustomResourceDefinition" + crdKinds = "customresourcedefinitions" + sourcesLabelKey = "duck.knative.dev/source" + sourcesLabelValue = "true" + sourceListGroup = "client.knative.dev" + sourceListVersion = "v1alpha1" + sourceListKind = "SourceList" + channelLabelValue = "true" + channelListVersion = "v1" + channelListKind = "ChannelList" + channelKind = "Channel" +) + +// KnDynamicClient to client-go Dynamic client. All methods are relative to the +// namespace specified during construction +type KnDynamicClient interface { + // Namespace in which this client is operating for + Namespace() string + + // ListCRDs returns list of CRDs with their type and name + ListCRDs(ctx context.Context, options metav1.ListOptions) (*unstructured.UnstructuredList, error) + + // ListSourcesTypes returns list of eventing sources CRDs + ListSourcesTypes(ctx context.Context) (*unstructured.UnstructuredList, error) + + // ListSources returns list of available source objects + ListSources(ctx context.Context, types ...WithType) (*unstructured.UnstructuredList, error) + + // ListSourcesUsingGVKs returns list of available source objects using given list of GVKs + ListSourcesUsingGVKs(context.Context, *[]schema.GroupVersionKind, ...WithType) (*unstructured.UnstructuredList, error) + + // ListChannelsTypes returns installed knative channel CRDs + ListChannelsTypes(ctx context.Context) (*unstructured.UnstructuredList, error) + + // ListChannelsUsingGVKs returns list of available channel objects using given list of GVKs + ListChannelsUsingGVKs(context.Context, *[]schema.GroupVersionKind, ...WithType) (*unstructured.UnstructuredList, error) + + // RawClient returns the raw dynamic client interface + RawClient() dynamic.Interface +} + +// knDynamicClient is a combination of client-go Dynamic client interface and namespace +type knDynamicClient struct { + client dynamic.Interface + namespace string +} + +// NewKnDynamicClient is to invoke Eventing Sources Client API to create object +func NewKnDynamicClient(client dynamic.Interface, namespace string) KnDynamicClient { + return &knDynamicClient{ + client: client, + namespace: namespace, + } +} + +// Return the client's namespace +func (c *knDynamicClient) Namespace() string { + return c.namespace +} + +// TODO(navidshaikh): Use ListConfigs here instead of ListOptions +// ListCRDs returns list of installed CRDs in the cluster and filters based on the given options +func (c *knDynamicClient) ListCRDs(ctx context.Context, options metav1.ListOptions) (*unstructured.UnstructuredList, error) { + gvr := schema.GroupVersionResource{ + Group: crdGroup, + Version: crdVersion, + Resource: crdKinds, + } + + uList, err := c.client.Resource(gvr).List(ctx, options) + if err != nil { + return nil, err + } + + return uList, nil +} + +// ListSourcesTypes returns installed knative eventing sources CRDs +func (c *knDynamicClient) ListSourcesTypes(ctx context.Context) (*unstructured.UnstructuredList, error) { + options := metav1.ListOptions{} + sourcesLabels := labels.Set{sourcesLabelKey: sourcesLabelValue} + options.LabelSelector = sourcesLabels.String() + return c.ListCRDs(ctx, options) +} + +// ListChannelsTypes returns installed knative channel CRDs +func (c *knDynamicClient) ListChannelsTypes(ctx context.Context) (*unstructured.UnstructuredList, error) { + var ChannelTypeList unstructured.UnstructuredList + options := metav1.ListOptions{} + channelsLabels := labels.Set{messaging.SubscribableDuckVersionAnnotation: channelLabelValue} + options.LabelSelector = channelsLabels.String() + uList, err := c.ListCRDs(ctx, options) + if err != nil { + return nil, err + } + ChannelTypeList.Object = uList.Object + for _, channelType := range uList.Items { + content := channelType.UnstructuredContent() + channelTypeKind, _, err := unstructured.NestedString(content, "spec", "names", "kind") + if err != nil { + return nil, err + } + if !util.SliceContainsIgnoreCase([]string{channelKind}, channelTypeKind) { + ChannelTypeList.Items = append(ChannelTypeList.Items, channelType) + } + } + return &ChannelTypeList, nil +} + +func (c knDynamicClient) RawClient() dynamic.Interface { + return c.client +} + +// ListSources returns list of available sources objects +// Provide the list of source types as for example: WithTypes("pingsource", "apiserversource"...) to list +// only given types of source objects +func (c *knDynamicClient) ListSources(ctx context.Context, types ...WithType) (*unstructured.UnstructuredList, error) { + var ( + sourceList unstructured.UnstructuredList + options metav1.ListOptions + ) + sourceTypes, err := c.ListSourcesTypes(ctx) + if err != nil { + return nil, err + } + + if sourceTypes == nil || len(sourceTypes.Items) == 0 { + return nil, errors.New("no sources found on the backend, please verify the installation") + } + + namespace := c.Namespace() + filters := WithTypes(types).List() + // For each source type available, find out each source types objects + for i := range sourceTypes.Items { + source := &sourceTypes.Items[i] + // find source kind before hand to fail early + sourceKind, err := kindFromUnstructured(source) + if err != nil { + return nil, err + } + + if len(filters) > 0 && !util.SliceContainsIgnoreCase(filters, sourceKind) { + continue + } + + // find source's GVR from unstructured source type object + gvr, err := gvrFromUnstructured(source) + if err != nil { + return nil, err + } + + // list objects of source type with this GVR + sList, err := c.client.Resource(gvr).Namespace(namespace).List(ctx, options) + if err != nil { + return nil, err + } + + if len(sList.Items) > 0 { + sourceList.Items = append(sourceList.Items, sList.Items...) + } + } + if len(sourceList.Items) > 0 { + sourceList.SetGroupVersionKind(schema.GroupVersionKind{Group: sourceListGroup, Version: sourceListVersion, Kind: sourceListKind}) + } + return &sourceList, nil +} + +// ListSourcesUsingGVKs returns list of available source objects using given list of GVKs +func (c *knDynamicClient) ListSourcesUsingGVKs(ctx context.Context, gvks *[]schema.GroupVersionKind, types ...WithType) (*unstructured.UnstructuredList, error) { + if gvks == nil { + return nil, nil + } + + var ( + sourceList unstructured.UnstructuredList + options metav1.ListOptions + ) + namespace := c.Namespace() + filters := WithTypes(types).List() + + for _, gvk := range *gvks { + if len(filters) > 0 && !util.SliceContainsIgnoreCase(filters, gvk.Kind) { + continue + } + + gvr := gvk.GroupVersion().WithResource(strings.ToLower(gvk.Kind) + "s") + + // list objects of source type with this GVR + sList, err := c.client.Resource(gvr).Namespace(namespace).List(ctx, options) + if err != nil { + return nil, err + } + + if len(sList.Items) > 0 { + sourceList.Items = append(sourceList.Items, sList.Items...) + } + } + if len(sourceList.Items) > 0 { + sourceList.SetGroupVersionKind(schema.GroupVersionKind{Group: sourceListGroup, Version: sourceListVersion, Kind: sourceListKind}) + } + return &sourceList, nil +} + +// ListChannelsUsingGVKs returns list of available channel objects using given list of GVKs +func (c *knDynamicClient) ListChannelsUsingGVKs(ctx context.Context, gvks *[]schema.GroupVersionKind, types ...WithType) (*unstructured.UnstructuredList, error) { + if gvks == nil { + return nil, nil + } + + var ( + channelList unstructured.UnstructuredList + options metav1.ListOptions + ) + namespace := c.Namespace() + filters := WithTypes(types).List() + + for _, gvk := range *gvks { + if len(filters) > 0 && !util.SliceContainsIgnoreCase(filters, gvk.Kind) { + continue + } + + gvr := gvk.GroupVersion().WithResource(strings.ToLower(gvk.Kind) + "s") + + // list objects of channel type with this GVR + cList, err := c.client.Resource(gvr).Namespace(namespace).List(ctx, options) + if err != nil { + return nil, err + } + + if len(cList.Items) > 0 { + channelList.Items = append(channelList.Items, cList.Items...) + } + } + if len(channelList.Items) > 0 { + channelList.SetGroupVersionKind(schema.GroupVersionKind{Group: messaging.GroupName, Version: channelListVersion, Kind: channelListKind}) + } + return &channelList, nil +} diff --git a/vendor/knative.dev/client-pkg/pkg/dynamic/client_mock.go b/vendor/knative.dev/client-pkg/pkg/dynamic/client_mock.go new file mode 100644 index 0000000000..c856f1086c --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/dynamic/client_mock.go @@ -0,0 +1,144 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dynamic + +import ( + "context" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/dynamic" + "knative.dev/client-pkg/pkg/util/mock" +) + +// MockKnDynamicClient is a combine of test object and recorder +type MockKnDynamicClient struct { + t *testing.T + recorder *ClientRecorder +} + +// NewMockKnDynamicClient returns a new mock instance which you need to record for +func NewMockKnDynamicClient(t *testing.T, ns ...string) *MockKnDynamicClient { + namespace := "default" + if len(ns) > 0 { + namespace = ns[0] + } + return &MockKnDynamicClient{ + t: t, + recorder: &ClientRecorder{mock.NewRecorder(t, namespace)}, + } +} + +// Ensure that the interface is implemented +var _ KnDynamicClient = &MockKnDynamicClient{} + +// ClientRecorder is recorder for eventing objects +type ClientRecorder struct { + r *mock.Recorder +} + +// Recorder returns the recorder for registering API calls +func (c *MockKnDynamicClient) Recorder() *ClientRecorder { + return c.recorder +} + +// Namespace of this client +func (c *MockKnDynamicClient) Namespace() string { + return c.recorder.r.Namespace() +} + +// ListCRDs returns list of installed CRDs in the cluster and filters based on the given options +func (dr *ClientRecorder) ListCRDs(options interface{}, ulist *unstructured.UnstructuredList, err error) { + dr.r.Add("ListCRDs", []interface{}{options}, []interface{}{ulist, err}) +} + +// ListCRDs returns list of installed CRDs in the cluster and filters based on the given options +func (c *MockKnDynamicClient) ListCRDs(ctx context.Context, options metav1.ListOptions) (*unstructured.UnstructuredList, error) { + call := c.recorder.r.VerifyCall("ListCRDs", options) + return call.Result[0].(*unstructured.UnstructuredList), mock.ErrorOrNil(call.Result[1]) +} + +// ListSourcesTypes returns installed knative eventing sources CRDs +func (dr *ClientRecorder) ListSourcesTypes(ulist *unstructured.UnstructuredList, err error) { + dr.r.Add("ListSourcesTypes", []interface{}{}, []interface{}{ulist, err}) +} + +// ListSourcesTypes returns installed knative eventing sources CRDs +func (c *MockKnDynamicClient) ListSourcesTypes(context.Context) (*unstructured.UnstructuredList, error) { + call := c.recorder.r.VerifyCall("ListSourcesTypes") + return call.Result[0].(*unstructured.UnstructuredList), mock.ErrorOrNil(call.Result[1]) +} + +// ListChannelsTypes returns installed knative messaging CRDs +func (dr *ClientRecorder) ListChannelsTypes(ulist *unstructured.UnstructuredList, err error) { + dr.r.Add("ListChannelsTypes", []interface{}{}, []interface{}{ulist, err}) +} + +// ListChannelsTypes returns installed knative messaging CRDs +func (c *MockKnDynamicClient) ListChannelsTypes(context.Context) (*unstructured.UnstructuredList, error) { + call := c.recorder.r.VerifyCall("ListChannelsTypes") + return call.Result[0].(*unstructured.UnstructuredList), mock.ErrorOrNil(call.Result[1]) +} + +// ListSources returns list of available sources objects +func (dr *ClientRecorder) ListSources(types interface{}, ulist *unstructured.UnstructuredList, err error) { + dr.r.Add("ListSources", []interface{}{types}, []interface{}{ulist, err}) +} + +// ListSources returns list of available sources objects +func (c *MockKnDynamicClient) ListSources(ctx context.Context, types ...WithType) (*unstructured.UnstructuredList, error) { + call := c.recorder.r.VerifyCall("ListSources") + return call.Result[0].(*unstructured.UnstructuredList), mock.ErrorOrNil(call.Result[1]) +} + +// RawClient creates a client +func (dr *ClientRecorder) RawClient(dynamicInterface dynamic.Interface) { + dr.r.Add("RawClient", []interface{}{}, []interface{}{dynamicInterface}) +} + +// RawClient creates a client +func (c *MockKnDynamicClient) RawClient() (dynamicInterface dynamic.Interface) { + call := c.recorder.r.VerifyCall("RawClient") + return call.Result[0].(dynamic.Interface) +} + +// ListSourcesUsingGVKs returns list of available source objects using given list of GVKs +func (dr *ClientRecorder) ListSourcesUsingGVKs(gvks interface{}, types interface{}, ulist *unstructured.UnstructuredList, err error) { + dr.r.Add("ListSourcesUsingGVKs", []interface{}{gvks, types}, []interface{}{ulist, err}) +} + +// ListSourcesUsingGVKs returns list of available source objects using given list of GVKs +func (c *MockKnDynamicClient) ListSourcesUsingGVKs(ctx context.Context, gvks *[]schema.GroupVersionKind, types ...WithType) (*unstructured.UnstructuredList, error) { + call := c.recorder.r.VerifyCall("ListSourcesUsingGVKs") + return call.Result[0].(*unstructured.UnstructuredList), mock.ErrorOrNil(call.Result[1]) +} + +// Validate validates whether every recorded action has been called +func (dr *ClientRecorder) Validate() { + dr.r.CheckThatAllRecordedMethodsHaveBeenCalled() +} + +// ListChannelsUsingGVKs returns list of available channel objects using given list of GVKs +func (dr *ClientRecorder) ListChannelsUsingGVKs(gvks interface{}, types interface{}, ulist *unstructured.UnstructuredList, err error) { + dr.r.Add("ListChannelsUsingGVKs", []interface{}{gvks, types}, []interface{}{ulist, err}) +} + +// ListChannelsUsingGVKs returns list of available channel objects using given list of GVKs +func (c *MockKnDynamicClient) ListChannelsUsingGVKs(ctx context.Context, gvks *[]schema.GroupVersionKind, types ...WithType) (*unstructured.UnstructuredList, error) { + call := c.recorder.r.VerifyCall("ListChannelsUsingGVKs") + return call.Result[0].(*unstructured.UnstructuredList), mock.ErrorOrNil(call.Result[1]) +} diff --git a/vendor/knative.dev/client-pkg/pkg/dynamic/fake/fake.go b/vendor/knative.dev/client-pkg/pkg/dynamic/fake/fake.go new file mode 100644 index 0000000000..205523257b --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/dynamic/fake/fake.go @@ -0,0 +1,44 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fake + +import ( + "context" + + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/runtime" + + "knative.dev/client-pkg/pkg/dynamic" + + eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" + messagingv1 "knative.dev/eventing/pkg/apis/messaging/v1" + sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1" + sourcesv1beta2 "knative.dev/eventing/pkg/apis/sources/v1beta2" + dynamicclientfake "knative.dev/pkg/injection/clients/dynamicclient/fake" + servingv1 "knative.dev/serving/pkg/apis/serving/v1" +) + +// CreateFakeKnDynamicClient gives you a dynamic client for testing containing the given objects. +func CreateFakeKnDynamicClient(testNamespace string, objects ...runtime.Object) dynamic.KnDynamicClient { + scheme := runtime.NewScheme() + servingv1.AddToScheme(scheme) + eventingv1.AddToScheme(scheme) + messagingv1.AddToScheme(scheme) + sourcesv1.AddToScheme(scheme) + sourcesv1beta2.AddToScheme(scheme) + apiextensionsv1.AddToScheme(scheme) + _, dynamicClient := dynamicclientfake.With(context.TODO(), scheme, objects...) + return dynamic.NewKnDynamicClient(dynamicClient, testNamespace) +} diff --git a/vendor/knative.dev/client-pkg/pkg/dynamic/lib.go b/vendor/knative.dev/client-pkg/pkg/dynamic/lib.go new file mode 100644 index 0000000000..b91a56570b --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/dynamic/lib.go @@ -0,0 +1,148 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dynamic + +import ( + "fmt" + "strings" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// gvrFromUnstructured takes a unstructured object of CRD type and finds GVR from its spec +func gvrFromUnstructured(u *unstructured.Unstructured) (gvr schema.GroupVersionResource, err error) { + group, err := groupFromUnstructured(u) + if err != nil { + return gvr, err + } + + version, err := versionFromUnstructured(u) + if err != nil { + return gvr, err + } + + resource, err := resourceFromUnstructured(u) + if err != nil { + return gvr, err + } + + return schema.GroupVersionResource{ + Group: group, + Version: version, + Resource: resource, + }, nil +} + +func groupFromUnstructured(u *unstructured.Unstructured) (string, error) { + content := u.UnstructuredContent() + group, found, err := unstructured.NestedString(content, "spec", "group") + if err != nil || !found { + return "", fmt.Errorf("can't find group for source GVR: %w", err) + } + return group, nil +} + +func versionFromUnstructured(u *unstructured.Unstructured) (version string, err error) { + content := u.UnstructuredContent() + versions, found, err := unstructured.NestedSlice(content, "spec", "versions") + if err != nil || !found || len(versions) == 0 { + // fallback to .spec.version + version, found, err = unstructured.NestedString(content, "spec", "version") + if err != nil || !found { + return version, fmt.Errorf("can't find version for source GVR: %w", err) + } + } else { + for _, v := range versions { + if vmap, ok := v.(map[string]interface{}); ok { + // find the version name which is being served + if vmap["served"] == true { + version = vmap["name"].(string) + break + } + } + } + } + // if we could find the version at all + if version == "" { + err = fmt.Errorf("can't find version for source GVR") + } + return version, err +} + +func resourceFromUnstructured(u *unstructured.Unstructured) (string, error) { + content := u.UnstructuredContent() + resource, found, err := unstructured.NestedString(content, "spec", "names", "plural") + if err != nil || !found { + return "", fmt.Errorf("can't find resource for source GVR: %w", err) + } + return resource, nil +} + +func kindFromUnstructured(u *unstructured.Unstructured) (string, error) { + content := u.UnstructuredContent() + kind, found, err := unstructured.NestedString(content, "spec", "names", "kind") + if !found || err != nil { + return "", fmt.Errorf("can't find source kind from source CRD: %w", err) + } + return kind, nil +} + +// TypesFilter for keeping list of sources types to filter upo +type TypesFilter []string + +// WithType function for easy filtering on source types +type WithType func(filters *TypesFilter) + +// WithTypes for recording the source type filtering function WithType +type WithTypes []WithType + +// WithTypeFilter can be used to filter based on source type name +func WithTypeFilter(name string) WithType { + return func(filters *TypesFilter) { + *filters = append(*filters, name) + } +} + +// List returns the source type name list recorded via WithTypeFilter +func (types WithTypes) List() []string { + var stypes TypesFilter + for _, f := range types { + f(&stypes) + } + return stypes +} + +// UnstructuredCRDFromGVK constructs an unstructured object using the given GVK +func UnstructuredCRDFromGVK(gvk schema.GroupVersionKind) *unstructured.Unstructured { + name := fmt.Sprintf("%ss.%s", strings.ToLower(gvk.Kind), gvk.Group) + plural := fmt.Sprintf("%ss", strings.ToLower(gvk.Kind)) + u := &unstructured.Unstructured{} + u.SetUnstructuredContent(map[string]interface{}{ + "metadata": map[string]interface{}{ + "name": name, + }, + "spec": map[string]interface{}{ + "group": gvk.Group, + "version": gvk.Version, + "names": map[string]interface{}{ + "kind": gvk.Kind, + "plural": plural, + }, + }, + }) + + return u +} diff --git a/vendor/knative.dev/client-pkg/pkg/errors/errors.go b/vendor/knative.dev/client-pkg/pkg/errors/errors.go new file mode 100644 index 0000000000..fba16e257e --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/errors/errors.go @@ -0,0 +1,50 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package errors + +import ( + "fmt" + "strings" + "unicode" + "unicode/utf8" +) + +func NewInvalidCRD(apiGroup string) *KNError { + parts := strings.Split(apiGroup, ".") + name := parts[0] + msg := fmt.Sprintf("no or newer Knative %s API found on the backend, please verify the installation or "+ + "update the 'kn' client", firstCharToUpper(name)) + return NewKNError(msg) +} + +func newNoRouteToHost(errString string) *KNError { + parts := strings.SplitAfter(errString, "dial tcp") + if len(parts) == 2 { + return NewKNError(fmt.Sprintf("error connecting to the cluster, please verify connection at: %s", strings.Trim(parts[1], " "))) + } + return NewKNError(fmt.Sprintf("error connecting to the cluster: %s", errString)) +} + +func newNoKubeConfig(errString string) *KNError { + return NewKNError("no kubeconfig has been provided, please use a valid configuration to connect to the cluster") +} + +func firstCharToUpper(s string) string { + if len(s) == 0 { + return s + } + r, n := utf8.DecodeRuneInString(s) + return string(unicode.ToUpper(r)) + s[n:] +} diff --git a/vendor/knative.dev/client-pkg/pkg/errors/factory.go b/vendor/knative.dev/client-pkg/pkg/errors/factory.go new file mode 100644 index 0000000000..9d8f51612a --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/errors/factory.go @@ -0,0 +1,90 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package errors + +import ( + "errors" + "net/http" + "strings" + + api_errors "k8s.io/apimachinery/pkg/api/errors" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func isCRDError(status api_errors.APIStatus) bool { + for _, cause := range status.Status().Details.Causes { + if strings.HasPrefix(cause.Message, "404") && cause.Type == v1.CauseTypeUnexpectedServerResponse { + return true + } + } + return false +} + +func isNoRouteToHostError(err error) bool { + return strings.Contains(err.Error(), "no route to host") || strings.Contains(err.Error(), "i/o timeout") +} + +func isEmptyConfigError(err error) bool { + return strings.Contains(err.Error(), "no configuration has been provided") +} + +func isStatusError(err error) bool { + var errAPIStatus api_errors.APIStatus + return errors.As(err, &errAPIStatus) +} + +func newStatusError(err error) error { + var errAPIStatus api_errors.APIStatus + errors.As(err, &errAPIStatus) + + if errAPIStatus.Status().Details == nil { + return err + } + var knerr *KNError + if isCRDError(errAPIStatus) { + knerr = NewInvalidCRD(errAPIStatus.Status().Details.Group) + knerr.Status = errAPIStatus + return knerr + } + return err +} + +// Retrieves a custom error struct based on the original error APIStatus struct +// Returns the original error struct in case it can't identify the kind of APIStatus error +func GetError(err error) error { + if err == nil { + return nil + } + + switch { + case isStatusError(err): + return newStatusError(err) + case isEmptyConfigError(err): + return newNoKubeConfig(err.Error()) + case isNoRouteToHostError(err): + return newNoRouteToHost(err.Error()) + default: + return err + } +} + +// IsForbiddenError returns true if given error can be converted to API status and of type forbidden access else false +func IsForbiddenError(err error) bool { + var errAPIStatus api_errors.APIStatus + if !errors.As(err, &errAPIStatus) { + return false + } + return errAPIStatus.Status().Code == int32(http.StatusForbidden) +} diff --git a/vendor/knative.dev/client-pkg/pkg/errors/knerror.go b/vendor/knative.dev/client-pkg/pkg/errors/knerror.go new file mode 100644 index 0000000000..52eda3f25b --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/errors/knerror.go @@ -0,0 +1,25 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package errors + +func NewKNError(msg string) *KNError { + return &KNError{ + msg: msg, + } +} + +func (kne *KNError) Error() string { + return kne.msg +} diff --git a/vendor/knative.dev/client-pkg/pkg/errors/types.go b/vendor/knative.dev/client-pkg/pkg/errors/types.go new file mode 100644 index 0000000000..ecc324ac1c --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/errors/types.go @@ -0,0 +1,22 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package errors + +import api_errors "k8s.io/apimachinery/pkg/api/errors" + +type KNError struct { + Status api_errors.APIStatus + msg string +} diff --git a/vendor/knative.dev/client-pkg/pkg/eventing/v1/client.go b/vendor/knative.dev/client-pkg/pkg/eventing/v1/client.go new file mode 100644 index 0000000000..8e502996dc --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/eventing/v1/client.go @@ -0,0 +1,524 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + "context" + "fmt" + "time" + + apis_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/util/retry" + "knative.dev/client-pkg/pkg/config" + v1 "knative.dev/eventing/pkg/apis/duck/v1" + eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" + "knative.dev/eventing/pkg/client/clientset/versioned/scheme" + clientv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1" + duckv1 "knative.dev/pkg/apis/duck/v1" + + kn_errors "knative.dev/client-pkg/pkg/errors" + "knative.dev/client-pkg/pkg/util" + "knative.dev/client-pkg/pkg/wait" +) + +type TriggerUpdateFunc func(origTrigger *eventingv1.Trigger) (*eventingv1.Trigger, error) +type BrokerUpdateFunc func(origBroker *eventingv1.Broker) (*eventingv1.Broker, error) + +// KnEventingClient to Eventing Sources. All methods are relative to the +// namespace specified during construction +type KnEventingClient interface { + // Namespace in which this client is operating for + Namespace() string + // CreateTrigger is used to create an instance of trigger + CreateTrigger(ctx context.Context, trigger *eventingv1.Trigger) error + // DeleteTrigger is used to delete an instance of trigger + DeleteTrigger(ctx context.Context, name string) error + // GetTrigger is used to get an instance of trigger + GetTrigger(ctx context.Context, name string) (*eventingv1.Trigger, error) + // ListTriggers returns list of trigger CRDs + ListTriggers(ctx context.Context) (*eventingv1.TriggerList, error) + // UpdateTrigger is used to update an instance of trigger + UpdateTrigger(ctx context.Context, trigger *eventingv1.Trigger) error + // UpdateTriggerWithRetry is used to update an instance of trigger + UpdateTriggerWithRetry(ctx context.Context, name string, updateFunc TriggerUpdateFunc, nrRetries int) error + // CreateBroker is used to create an instance of broker + CreateBroker(ctx context.Context, broker *eventingv1.Broker) error + // GetBroker is used to get an instance of broker + GetBroker(ctx context.Context, name string) (*eventingv1.Broker, error) + // DeleteBroker is used to delete an instance of broker + DeleteBroker(ctx context.Context, name string, timeout time.Duration) error + // ListBrokers returns list of broker CRDs + ListBrokers(ctx context.Context) (*eventingv1.BrokerList, error) + // UpdateBroker is used to update an instance of broker + UpdateBroker(ctx context.Context, broker *eventingv1.Broker) error + // UpdateBrokerWithRetry is used to update an instance of broker + UpdateBrokerWithRetry(ctx context.Context, name string, updateFunc BrokerUpdateFunc, nrRetries int) error +} + +// KnEventingClient is a combination of Sources client interface and namespace +// Temporarily help to add sources dependencies +// May be changed when adding real sources features +type knEventingClient struct { + client clientv1.EventingV1Interface + namespace string +} + +// NewKnEventingClient is to invoke Eventing Sources Client API to create object +func NewKnEventingClient(client clientv1.EventingV1Interface, namespace string) KnEventingClient { + return &knEventingClient{ + client: client, + namespace: namespace, + } +} + +// CreateTrigger is used to create an instance of trigger +func (c *knEventingClient) CreateTrigger(ctx context.Context, trigger *eventingv1.Trigger) error { + _, err := c.client.Triggers(c.namespace).Create(ctx, trigger, meta_v1.CreateOptions{}) + if err != nil { + return kn_errors.GetError(err) + } + return nil +} + +// DeleteTrigger is used to delete an instance of trigger +func (c *knEventingClient) DeleteTrigger(ctx context.Context, name string) error { + err := c.client.Triggers(c.namespace).Delete(ctx, name, apis_v1.DeleteOptions{}) + if err != nil { + return kn_errors.GetError(err) + } + return nil +} + +// GetTrigger is used to get an instance of trigger +func (c *knEventingClient) GetTrigger(ctx context.Context, name string) (*eventingv1.Trigger, error) { + trigger, err := c.client.Triggers(c.namespace).Get(ctx, name, apis_v1.GetOptions{}) + if err != nil { + return nil, kn_errors.GetError(err) + } + err = updateEventingGVK(trigger) + if err != nil { + return nil, err + } + return trigger, nil +} + +func (c *knEventingClient) ListTriggers(ctx context.Context) (*eventingv1.TriggerList, error) { + triggerList, err := c.client.Triggers(c.namespace).List(ctx, apis_v1.ListOptions{}) + if err != nil { + return nil, kn_errors.GetError(err) + } + triggerListNew := triggerList.DeepCopy() + err = updateEventingGVK(triggerListNew) + if err != nil { + return nil, err + } + + triggerListNew.Items = make([]eventingv1.Trigger, len(triggerList.Items)) + for idx, trigger := range triggerList.Items { + triggerClone := trigger.DeepCopy() + err := updateEventingGVK(triggerClone) + if err != nil { + return nil, err + } + triggerListNew.Items[idx] = *triggerClone + } + return triggerListNew, nil +} + +// UpdateTrigger is used to update an instance of trigger +func (c *knEventingClient) UpdateTrigger(ctx context.Context, trigger *eventingv1.Trigger) error { + _, err := c.client.Triggers(c.namespace).Update(ctx, trigger, meta_v1.UpdateOptions{}) + if err != nil { + return kn_errors.GetError(err) + } + return nil +} + +func (c *knEventingClient) UpdateTriggerWithRetry(ctx context.Context, name string, updateFunc TriggerUpdateFunc, nrRetries int) error { + return updateTriggerWithRetry(ctx, c, name, updateFunc, nrRetries) +} + +func updateTriggerWithRetry(ctx context.Context, c KnEventingClient, name string, updateFunc TriggerUpdateFunc, nrRetries int) error { + b := config.DefaultRetry + b.Steps = nrRetries + updateTriggerFunc := func() error { + return updateTrigger(ctx, c, name, updateFunc) + } + err := retry.RetryOnConflict(b, updateTriggerFunc) + return err +} + +func updateTrigger(ctx context.Context, c KnEventingClient, name string, updateFunc TriggerUpdateFunc) error { + trigger, err := c.GetTrigger(ctx, name) + if err != nil { + return err + } + if trigger.GetDeletionTimestamp() != nil { + return fmt.Errorf("can't update trigger %s because it has been marked for deletion", name) + } + updatedTrigger, err := updateFunc(trigger.DeepCopy()) + if err != nil { + return err + } + + return c.UpdateTrigger(ctx, updatedTrigger) +} + +// Namespace returns the namespace this client is bound to +func (c *knEventingClient) Namespace() string { + return c.namespace +} + +// update with the eventingv1 group + version +func updateEventingGVK(obj runtime.Object) error { + return util.UpdateGroupVersionKindWithScheme(obj, eventingv1.SchemeGroupVersion, scheme.Scheme) +} + +// TriggerBuilder is for building the trigger +type TriggerBuilder struct { + trigger *eventingv1.Trigger +} + +// NewTriggerBuilder for building trigger object +func NewTriggerBuilder(name string) *TriggerBuilder { + return &TriggerBuilder{&eventingv1.Trigger{ + ObjectMeta: meta_v1.ObjectMeta{ + Name: name, + }, + }} +} + +// WithGvk sets the GVK for the triggers (which otherwise remains empty +func (b *TriggerBuilder) WithGvk() *TriggerBuilder { + _ = updateEventingGVK(b.trigger) + return b +} + +// NewTriggerBuilderFromExisting for building the object from existing Trigger object +func NewTriggerBuilderFromExisting(trigger *eventingv1.Trigger) *TriggerBuilder { + return &TriggerBuilder{trigger: trigger.DeepCopy()} +} + +// Namespace for this trigger +func (b *TriggerBuilder) Namespace(ns string) *TriggerBuilder { + b.trigger.Namespace = ns + return b +} + +// Subscriber for the trigger to send to (it's a Sink actually) +func (b *TriggerBuilder) Subscriber(subscriber *duckv1.Destination) *TriggerBuilder { + b.trigger.Spec.Subscriber = *subscriber + return b +} + +// Broker to set the broker of trigger object +func (b *TriggerBuilder) Broker(broker string) *TriggerBuilder { + b.trigger.Spec.Broker = broker + + return b +} + +// InjectBroker to add annotation to setup default broker +func (b *TriggerBuilder) InjectBroker(inject bool) *TriggerBuilder { + if inject { + meta_v1.SetMetaDataAnnotation(&b.trigger.ObjectMeta, eventingv1.InjectionAnnotation, "enabled") + } else { + if meta_v1.HasAnnotation(b.trigger.ObjectMeta, eventingv1.InjectionAnnotation) { + delete(b.trigger.ObjectMeta.Annotations, eventingv1.InjectionAnnotation) + } + } + return b +} + +func (b *TriggerBuilder) Filters(filters map[string]string) *TriggerBuilder { + if len(filters) == 0 { + b.trigger.Spec.Filter = &eventingv1.TriggerFilter{} + return b + } + filter := b.trigger.Spec.Filter + if filter == nil { + filter = &eventingv1.TriggerFilter{} + b.trigger.Spec.Filter = filter + } + filter.Attributes = eventingv1.TriggerFilterAttributes{} + for k, v := range filters { + filter.Attributes[k] = v + } + return b +} + +// Build to return an instance of trigger object +func (b *TriggerBuilder) Build() *eventingv1.Trigger { + return b.trigger +} + +// CreateBroker is used to create an instance of broker +func (c *knEventingClient) CreateBroker(ctx context.Context, broker *eventingv1.Broker) error { + _, err := c.client.Brokers(c.namespace).Create(ctx, broker, meta_v1.CreateOptions{}) + if err != nil { + return kn_errors.GetError(err) + } + return nil +} + +// GetBroker is used to get an instance of broker +func (c *knEventingClient) GetBroker(ctx context.Context, name string) (*eventingv1.Broker, error) { + broker, err := c.client.Brokers(c.namespace).Get(ctx, name, apis_v1.GetOptions{}) + if err != nil { + return nil, kn_errors.GetError(err) + } + err = updateEventingGVK(broker) + if err != nil { + return nil, err + } + return broker, nil +} + +// WatchBroker is used to create watcher object +func (c *knEventingClient) WatchBroker(ctx context.Context, name string, initialVersion string, timeout time.Duration) (watch.Interface, error) { + return wait.NewWatcherWithVersion(ctx, c.client.Brokers(c.namespace).Watch, c.client.RESTClient(), c.namespace, "brokers", name, initialVersion, timeout) +} + +// DeleteBroker is used to delete an instance of broker and wait for completion until given timeout +// For `timeout == 0` delete is performed async without any wait +func (c *knEventingClient) DeleteBroker(ctx context.Context, name string, timeout time.Duration) error { + broker, err := c.GetBroker(ctx, name) + if err != nil { + return err + } + if broker.GetDeletionTimestamp() != nil { + return fmt.Errorf("can't delete broker '%s' because it has been already marked for deletion", name) + } + if timeout == 0 { + return c.deleteBroker(ctx, name, apis_v1.DeletePropagationBackground) + } + waitC := make(chan error) + go func() { + waitForEvent := wait.NewWaitForEvent("broker", c.WatchBroker, func(evt *watch.Event) bool { return evt.Type == watch.Deleted }) + err, _ := waitForEvent.Wait(ctx, name, broker.ResourceVersion, wait.Options{Timeout: &timeout}, wait.NoopMessageCallback()) + waitC <- err + }() + err = c.deleteBroker(ctx, name, apis_v1.DeletePropagationForeground) + if err != nil { + return err + } + return <-waitC +} + +// deleteBroker is used to delete an instance of broker +func (c *knEventingClient) deleteBroker(ctx context.Context, name string, propagationPolicy apis_v1.DeletionPropagation) error { + err := c.client.Brokers(c.namespace).Delete(ctx, name, apis_v1.DeleteOptions{PropagationPolicy: &propagationPolicy}) + if err != nil { + return kn_errors.GetError(err) + } + return nil +} + +// ListBrokers is used to retrieve the list of broker instances +func (c *knEventingClient) ListBrokers(ctx context.Context) (*eventingv1.BrokerList, error) { + brokerList, err := c.client.Brokers(c.namespace).List(ctx, apis_v1.ListOptions{}) + if err != nil { + return nil, kn_errors.GetError(err) + } + brokerListNew := brokerList.DeepCopy() + err = updateEventingGVK(brokerListNew) + if err != nil { + return nil, err + } + + brokerListNew.Items = make([]eventingv1.Broker, len(brokerList.Items)) + for idx, trigger := range brokerList.Items { + triggerClone := trigger.DeepCopy() + err := updateEventingGVK(triggerClone) + if err != nil { + return nil, err + } + brokerListNew.Items[idx] = *triggerClone + } + return brokerListNew, nil +} + +// UpdateBroker is used to update an instance of broker +func (c *knEventingClient) UpdateBroker(ctx context.Context, broker *eventingv1.Broker) error { + _, err := c.client.Brokers(c.namespace).Update(ctx, broker, meta_v1.UpdateOptions{}) + if err != nil { + return kn_errors.GetError(err) + } + return nil +} + +func (c *knEventingClient) UpdateBrokerWithRetry(ctx context.Context, name string, updateFunc BrokerUpdateFunc, nrRetries int) error { + return updateBrokerWithRetry(ctx, c, name, updateFunc, nrRetries) +} + +func updateBrokerWithRetry(ctx context.Context, c KnEventingClient, name string, updateFunc BrokerUpdateFunc, nrRetries int) error { + b := config.DefaultRetry + b.Steps = nrRetries + updateBrokerFunc := func() error { + return updateBroker(ctx, c, name, updateFunc) + } + err := retry.RetryOnConflict(b, updateBrokerFunc) + return err +} + +func updateBroker(ctx context.Context, c KnEventingClient, name string, updateFunc BrokerUpdateFunc) error { + broker, err := c.GetBroker(ctx, name) + if err != nil { + return err + } + if broker.GetDeletionTimestamp() != nil { + return fmt.Errorf("can't update broker %s because it has been marked for deletion", name) + } + updatedBroker, err := updateFunc(broker.DeepCopy()) + if err != nil { + return err + } + + return c.UpdateBroker(ctx, updatedBroker) +} + +// BrokerBuilder is for building the broker +type BrokerBuilder struct { + broker *eventingv1.Broker +} + +// NewBrokerBuilder for building broker object +func NewBrokerBuilder(name string) *BrokerBuilder { + return &BrokerBuilder{broker: &eventingv1.Broker{ + ObjectMeta: meta_v1.ObjectMeta{ + Name: name, + }, + }} +} + +// NewBrokerBuilderFromExisting returns broker builder from original broker +func NewBrokerBuilderFromExisting(broker *eventingv1.Broker) *BrokerBuilder { + return &BrokerBuilder{ + broker: broker, + } +} + +// WithGvk add the GVK coordinates for read tests +func (b *BrokerBuilder) WithGvk() *BrokerBuilder { + _ = updateEventingGVK(b.broker) + return b +} + +// Namespace for broker builder +func (b *BrokerBuilder) Namespace(ns string) *BrokerBuilder { + b.broker.Namespace = ns + return b +} + +// Class for broker builder +func (b *BrokerBuilder) Class(class string) *BrokerBuilder { + if class == "" { + return b + } + if len(b.broker.Annotations) == 0 { + b.broker.Annotations = make(map[string]string) + } + b.broker.Annotations[eventingv1.BrokerClassAnnotationKey] = class + return b +} + +// DlSink for the broker builder +func (b *BrokerBuilder) DlSink(dlSink *duckv1.Destination) *BrokerBuilder { + empty := duckv1.Destination{} + if dlSink == nil || *dlSink == empty { + return b + } + if b.broker.Spec.Delivery == nil { + b.broker.Spec.Delivery = &v1.DeliverySpec{} + } + b.broker.Spec.Delivery.DeadLetterSink = dlSink + return b +} + +// Retry for the broker builder +func (b *BrokerBuilder) Retry(retry *int32) *BrokerBuilder { + if retry == nil || *retry == 0 { + return b + } + if b.broker.Spec.Delivery == nil { + b.broker.Spec.Delivery = &v1.DeliverySpec{} + } + b.broker.Spec.Delivery.Retry = retry + return b +} + +// Timeout for the broker builder +func (b *BrokerBuilder) Timeout(timeout *string) *BrokerBuilder { + if timeout == nil || *timeout == "" { + return b + } + if b.broker.Spec.Delivery == nil { + b.broker.Spec.Delivery = &v1.DeliverySpec{} + } + b.broker.Spec.Delivery.Timeout = timeout + return b +} + +// BackoffPolicy for the broker builder +func (b *BrokerBuilder) BackoffPolicy(policyType *v1.BackoffPolicyType) *BrokerBuilder { + if policyType == nil || *policyType == "" { + return b + } + if b.broker.Spec.Delivery == nil { + b.broker.Spec.Delivery = &v1.DeliverySpec{} + } + b.broker.Spec.Delivery.BackoffPolicy = policyType + return b +} + +// BackoffDelay for the broker builder +func (b *BrokerBuilder) BackoffDelay(backoffDelay *string) *BrokerBuilder { + if backoffDelay == nil || *backoffDelay == "" { + return b + } + if b.broker.Spec.Delivery == nil { + b.broker.Spec.Delivery = &v1.DeliverySpec{} + } + b.broker.Spec.Delivery.BackoffDelay = backoffDelay + return b +} + +// RetryAfterMax for the broker builder +func (b *BrokerBuilder) RetryAfterMax(max *string) *BrokerBuilder { + if max == nil || *max == "" { + return b + } + if b.broker.Spec.Delivery == nil { + b.broker.Spec.Delivery = &v1.DeliverySpec{} + } + b.broker.Spec.Delivery.RetryAfterMax = max + return b + +} + +// Config for the broker builder +func (b *BrokerBuilder) Config(config *duckv1.KReference) *BrokerBuilder { + b.broker.Spec.Config = config + return b + +} + +// Build to return an instance of broker object +func (b *BrokerBuilder) Build() *eventingv1.Broker { + return b.broker +} diff --git a/vendor/knative.dev/client-pkg/pkg/eventing/v1beta1/client.go b/vendor/knative.dev/client-pkg/pkg/eventing/v1beta1/client.go new file mode 100644 index 0000000000..8572bee18c --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/eventing/v1beta1/client.go @@ -0,0 +1,165 @@ +// Copyright © 2022 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 v1beta1 + +import ( + "context" + + apis_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + kn_errors "knative.dev/client-pkg/pkg/errors" + "knative.dev/client-pkg/pkg/util" + eventingv1beta1 "knative.dev/eventing/pkg/apis/eventing/v1beta1" + "knative.dev/eventing/pkg/client/clientset/versioned/scheme" + beta1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1beta1" + "knative.dev/pkg/apis" +) + +// KnEventingV1Beta1Client to Eventing Sources. All methods are relative to the +// namespace specified during construction +type KnEventingV1Beta1Client interface { + // Namespace in which this client is operating for + Namespace() string + // ListEventtypes is used to list eventtypes + ListEventtypes(ctx context.Context) (*eventingv1beta1.EventTypeList, error) + // GetEventtype is used to describe an eventtype + GetEventtype(ctx context.Context, name string) (*eventingv1beta1.EventType, error) + // CreateEventtype is used to create an eventtype + CreateEventtype(ctx context.Context, eventtype *eventingv1beta1.EventType) error + // DeleteEventtype is used to delete an eventtype + DeleteEventtype(ctx context.Context, name string) error +} + +// KnEventingV1Beta1Client is a client for eventing v1beta1 resources +type knEventingV1Beta1Client struct { + client beta1.EventingV1beta1Interface + namespace string +} + +// NewKnEventingV1Beta1Client is to invoke Eventing Types Client API to create object +func NewKnEventingV1Beta1Client(client beta1.EventingV1beta1Interface, namespace string) KnEventingV1Beta1Client { + return &knEventingV1Beta1Client{ + client: client, + namespace: namespace, + } +} + +func updateEventingBeta1GVK(obj runtime.Object) error { + return util.UpdateGroupVersionKindWithScheme(obj, eventingv1beta1.SchemeGroupVersion, scheme.Scheme) +} + +func (c *knEventingV1Beta1Client) Namespace() string { + return c.namespace +} + +func (c *knEventingV1Beta1Client) ListEventtypes(ctx context.Context) (*eventingv1beta1.EventTypeList, error) { + eventTypeList, err := c.client.EventTypes(c.namespace).List(ctx, apis_v1.ListOptions{}) + if err != nil { + return nil, kn_errors.GetError(err) + } + listNew := eventTypeList.DeepCopy() + err = updateEventingBeta1GVK(listNew) + if err != nil { + return nil, err + } + + listNew.Items = make([]eventingv1beta1.EventType, len(eventTypeList.Items)) + for idx, eventType := range eventTypeList.Items { + clone := eventType.DeepCopy() + err := updateEventingBeta1GVK(clone) + if err != nil { + return nil, err + } + listNew.Items[idx] = *clone + } + return listNew, nil +} + +func (c *knEventingV1Beta1Client) GetEventtype(ctx context.Context, name string) (*eventingv1beta1.EventType, error) { + eventType, err := c.client.EventTypes(c.namespace).Get(ctx, name, apis_v1.GetOptions{}) + if err != nil { + return nil, kn_errors.GetError(err) + } + err = updateEventingBeta1GVK(eventType) + if err != nil { + return nil, err + } + return eventType, nil +} + +func (c *knEventingV1Beta1Client) DeleteEventtype(ctx context.Context, name string) error { + err := c.client.EventTypes(c.namespace).Delete(ctx, name, apis_v1.DeleteOptions{}) + if err != nil { + return kn_errors.GetError(err) + } + return nil +} + +func (c *knEventingV1Beta1Client) CreateEventtype(ctx context.Context, eventtype *eventingv1beta1.EventType) error { + _, err := c.client.EventTypes(c.namespace).Create(ctx, eventtype, apis_v1.CreateOptions{}) + if err != nil { + return kn_errors.GetError(err) + } + return nil +} + +// EventtypeBuilder is for building the eventtype +type EventtypeBuilder struct { + eventtype *eventingv1beta1.EventType +} + +// NewEventtypeBuilder for building eventtype object +func NewEventtypeBuilder(name string) *EventtypeBuilder { + return &EventtypeBuilder{eventtype: &eventingv1beta1.EventType{ + ObjectMeta: apis_v1.ObjectMeta{ + Name: name, + }, + }} +} + +// WithGvk add the GVK coordinates for read tests +func (e *EventtypeBuilder) WithGvk() *EventtypeBuilder { + _ = updateEventingBeta1GVK(e.eventtype) + return e +} + +// Namespace for eventtype builder +func (e *EventtypeBuilder) Namespace(ns string) *EventtypeBuilder { + e.eventtype.Namespace = ns + return e +} + +// Type for eventtype builder +func (e *EventtypeBuilder) Type(ceType string) *EventtypeBuilder { + e.eventtype.Spec.Type = ceType + return e +} + +// Source for eventtype builder +func (e *EventtypeBuilder) Source(source *apis.URL) *EventtypeBuilder { + e.eventtype.Spec.Source = source + return e +} + +// Broker for eventtype builder +func (e *EventtypeBuilder) Broker(broker string) *EventtypeBuilder { + e.eventtype.Spec.Broker = broker + return e +} + +// Build to return an instance of eventtype object +func (e *EventtypeBuilder) Build() *eventingv1beta1.EventType { + return e.eventtype +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/client/client.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/client/client.go new file mode 100644 index 0000000000..bf3c372479 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/client/client.go @@ -0,0 +1,51 @@ +// 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 client + +import ( + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" + + "k8s.io/client-go/rest" +) + +type knSourceClient struct { + knSourceParams *types.KnSourceParams + namespace string + restConfig *rest.Config +} + +// NewKnSourceClient creates a new KnSourceClient with parameters and namespace +func NewKnSourceClient(knSourceParams *types.KnSourceParams, restConfig *rest.Config, namespace string) types.KnSourceClient { + return &knSourceClient{ + knSourceParams: knSourceParams, + namespace: namespace, + restConfig: restConfig, + } +} + +// KnSourceParams returns the client's KnSourceParams +func (client *knSourceClient) KnSourceParams() *types.KnSourceParams { + return client.knSourceParams +} + +// Namespace returns the client's namespace +func (client *knSourceClient) Namespace() string { + return client.namespace +} + +// RestConfig a Config object to do REST invocations +func (client *knSourceClient) RestConfig() *rest.Config { + return client.restConfig +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/create.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/create.go new file mode 100644 index 0000000000..5ef2870187 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/create.go @@ -0,0 +1,30 @@ +// 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 source + +import ( + "github.com/spf13/cobra" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" +) + +// NewCreateCommand for creating event sources +func NewCreateCommand(params *types.KnSourceParams) *cobra.Command { + createCmd := &cobra.Command{ + Use: "create NAME [flags]", + Short: "create {{.Name}} source", + Example: "{{.CreateExample}}", + } + return createCmd +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/delete.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/delete.go new file mode 100644 index 0000000000..722f377021 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/delete.go @@ -0,0 +1,30 @@ +// 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 source + +import ( + "github.com/spf13/cobra" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" +) + +// NewDeleteCommand for creating event sources +func NewDeleteCommand(params *types.KnSourceParams) *cobra.Command { + deleteCmd := &cobra.Command{ + Use: "delete NAME [flags]", + Short: "delete {{.Name}} source", + Example: "{{.DeleteExample}}", + } + return deleteCmd +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/describe.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/describe.go new file mode 100644 index 0000000000..efe18ef0ee --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/describe.go @@ -0,0 +1,30 @@ +// 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 source + +import ( + "github.com/spf13/cobra" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" +) + +// NewDescribeCommand for creating event sources +func NewDescribeCommand(params *types.KnSourceParams) *cobra.Command { + describeCmd := &cobra.Command{ + Use: "describe NAME [flags]", + Short: "describe {{.Name}} source", + Example: "{{.DescribeExample}}", + } + return describeCmd +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/list.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/list.go new file mode 100644 index 0000000000..a683a63823 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/list.go @@ -0,0 +1,30 @@ +// Copyright © 2021 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 source + +import ( + "github.com/spf13/cobra" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" +) + +// NewListCommand as the root group command +func NewListCommand(knSourceParams *types.KnSourceParams) *cobra.Command { + listCmd := &cobra.Command{ + Use: "list NAME [flags]", + Short: "list {{.Name}} source", + Example: "{{.ListExample}}", + } + return listCmd +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/source.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/source.go new file mode 100644 index 0000000000..6fb807cab0 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/source.go @@ -0,0 +1,30 @@ +// 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 source + +import ( + "github.com/spf13/cobra" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" +) + +// NewSourceCommand as the root group command +func NewSourceCommand(knSourceParams *types.KnSourceParams) *cobra.Command { + createCmd := &cobra.Command{ + Use: "source", + Short: "Knative eventing {{.Name}} source plugin", + Long: "Manage your Knative {{.Name}} eventing sources", + } + return createCmd +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/update.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/update.go new file mode 100644 index 0000000000..9da9137d7b --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source/update.go @@ -0,0 +1,30 @@ +// 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 source + +import ( + "github.com/spf13/cobra" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" +) + +// NewUpdateCommand for creating event sources +func NewUpdateCommand(params *types.KnSourceParams) *cobra.Command { + updateCmd := &cobra.Command{ + Use: "update NAME [flags]", + Short: "update {{.Name}} source", + Example: "{{.UpdateExample}}", + } + return updateCmd +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/core/root.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/core/root.go new file mode 100644 index 0000000000..b31b4dc542 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/core/root.go @@ -0,0 +1,91 @@ +// 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 core + +import ( + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" + + "github.com/spf13/cobra" +) + +func NewKnSourceCommand(knSourceFactory types.KnSourceFactory, + commandFactory types.CommandFactory, + flagsFactory types.FlagsFactory, + runEFactory types.RunEFactory) *cobra.Command { + knSourceParams := knSourceFactory.KnSourceParams() + rootCmd := commandFactory.SourceCommand() + + // Disable docs header + rootCmd.DisableAutoGenTag = true + + // Affects children as well + rootCmd.SilenceUsage = true + + // Prevents Cobra from dealing with errors as we deal with them in main.go + rootCmd.SilenceErrors = true + + if knSourceParams.Output != nil { + rootCmd.SetOut(knSourceParams.Output) + } + + listCmd := commandFactory.ListCommand() + addCommonFlags(knSourceParams, listCmd) + listCmd.Flags().AddFlagSet(flagsFactory.ListFlags()) + listCmd.RunE = runEFactory.ListRunE() + rootCmd.AddCommand(listCmd) + + createCmd := commandFactory.CreateCommand() + addCommonFlags(knSourceParams, createCmd) + addCreateUpdateFlags(knSourceParams, createCmd) + createCmd.Flags().AddFlagSet(flagsFactory.CreateFlags()) + createCmd.RunE = runEFactory.CreateRunE() + rootCmd.AddCommand(createCmd) + + deleteCmd := commandFactory.DeleteCommand() + addCommonFlags(knSourceParams, deleteCmd) + deleteCmd.Flags().AddFlagSet(flagsFactory.DeleteFlags()) + deleteCmd.RunE = runEFactory.DeleteRunE() + rootCmd.AddCommand(deleteCmd) + + updateCmd := commandFactory.UpdateCommand() + if updateCmd != nil { + addCommonFlags(knSourceParams, updateCmd) + addCreateUpdateFlags(knSourceParams, updateCmd) + updateCmd.Flags().AddFlagSet(flagsFactory.UpdateFlags()) + updateCmd.RunE = runEFactory.UpdateRunE() + rootCmd.AddCommand(updateCmd) + } + + describeCmd := commandFactory.DescribeCommand() + addCommonFlags(knSourceParams, describeCmd) + describeCmd.Flags().AddFlagSet(flagsFactory.DescribeFlags()) + describeCmd.RunE = runEFactory.DescribeRunE() + rootCmd.AddCommand(describeCmd) + + // Initialize default `help` cmd early to prevent unknown command errors + rootCmd.InitDefaultHelpCmd() + + return rootCmd +} + +// Private + +func addCommonFlags(knSourceParams *types.KnSourceParams, cmd *cobra.Command) { + knSourceParams.AddCommonFlags(cmd) +} + +func addCreateUpdateFlags(knSourceParams *types.KnSourceParams, cmd *cobra.Command) { + knSourceParams.AddCreateUpdateFlags(cmd) +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/boilerplate.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/boilerplate.go new file mode 100644 index 0000000000..a61ed50821 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/boilerplate.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 factories + +import ( + "k8s.io/client-go/rest" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" +) + +// KnSourceFactory + +func (f *DefautKnSourceFactory) KnSourceParams() *types.KnSourceParams { + if f.knSourceParams == nil { + f.knSourceParams = f.CreateKnSourceParams() + } + + return f.knSourceParams +} + +// CommandFactory + +func (f *DefautCommandFactory) KnSourceFactory() types.KnSourceFactory { + return f.knSourceFactory +} + +// FlagsFactory + +func (f *DefautFlagsFactory) KnSourceFactory() types.KnSourceFactory { + return f.knSourceFactory +} + +// RunEFactory + +func (f *DefautRunEFactory) KnSourceFactory() types.KnSourceFactory { + return f.knSourceFactory +} + +func (f *DefautRunEFactory) KnSourceClient(restConfig *rest.Config, namespace string) types.KnSourceClient { + return f.knSourceFactory.CreateKnSourceClient(restConfig, namespace) +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/command_factory.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/command_factory.go new file mode 100644 index 0000000000..93931897ba --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/command_factory.go @@ -0,0 +1,56 @@ +// 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 factories + +import ( + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" + + "github.com/spf13/cobra" +) + +type DefautCommandFactory struct { + knSourceFactory types.KnSourceFactory +} + +func NewDefaultCommandFactory(knSourceFactory types.KnSourceFactory) types.CommandFactory { + return &DefautCommandFactory{ + knSourceFactory: knSourceFactory, + } +} + +func (f *DefautCommandFactory) SourceCommand() *cobra.Command { + return source.NewSourceCommand(f.knSourceFactory.KnSourceParams()) +} + +func (f *DefautCommandFactory) ListCommand() *cobra.Command { + return source.NewListCommand(f.knSourceFactory.KnSourceParams()) +} + +func (f *DefautCommandFactory) CreateCommand() *cobra.Command { + return source.NewCreateCommand(f.knSourceFactory.KnSourceParams()) +} + +func (f *DefautCommandFactory) DeleteCommand() *cobra.Command { + return source.NewDeleteCommand(f.knSourceFactory.KnSourceParams()) +} + +func (f *DefautCommandFactory) UpdateCommand() *cobra.Command { + return source.NewUpdateCommand(f.knSourceFactory.KnSourceParams()) +} + +func (f *DefautCommandFactory) DescribeCommand() *cobra.Command { + return source.NewDescribeCommand(f.knSourceFactory.KnSourceParams()) +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/flags_factory.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/flags_factory.go new file mode 100644 index 0000000000..ea778323a3 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/flags_factory.go @@ -0,0 +1,68 @@ +// 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 factories + +import ( + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" + "knative.dev/client-pkg/pkg/kn/commands" + + "github.com/spf13/pflag" +) + +type DefautFlagsFactory struct { + knSourceFactory types.KnSourceFactory +} + +func NewDefaultFlagsFactory(knSourceFactory types.KnSourceFactory) types.FlagsFactory { + return &DefautFlagsFactory{ + knSourceFactory: knSourceFactory, + } +} + +func (f *DefautFlagsFactory) ListFlags() *pflag.FlagSet { + flagSet := pflag.NewFlagSet("list", pflag.ExitOnError) + f.addNamespaceFlag(flagSet) + return flagSet +} + +func (f *DefautFlagsFactory) CreateFlags() *pflag.FlagSet { + flagSet := pflag.NewFlagSet("create", pflag.ExitOnError) + f.addNamespaceFlag(flagSet) + return flagSet +} + +func (f *DefautFlagsFactory) DeleteFlags() *pflag.FlagSet { + flagSet := pflag.NewFlagSet("delete", pflag.ExitOnError) + f.addNamespaceFlag(flagSet) + return flagSet +} + +func (f *DefautFlagsFactory) UpdateFlags() *pflag.FlagSet { + flagSet := pflag.NewFlagSet("update", pflag.ExitOnError) + f.addNamespaceFlag(flagSet) + return flagSet +} + +func (f *DefautFlagsFactory) DescribeFlags() *pflag.FlagSet { + flagSet := pflag.NewFlagSet("describe", pflag.ExitOnError) + f.addNamespaceFlag(flagSet) + return flagSet +} + +// Private + +func (f *DefautFlagsFactory) addNamespaceFlag(flagSet *pflag.FlagSet) { + commands.AddNamespaceFlags(flagSet, false) +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/kn_source_factory.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/kn_source_factory.go new file mode 100644 index 0000000000..0ba8c7c5f3 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/kn_source_factory.go @@ -0,0 +1,49 @@ +// 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 factories + +import ( + "k8s.io/client-go/rest" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/client" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" + + "knative.dev/client-pkg/pkg/kn/commands/flags" +) + +type DefautKnSourceFactory struct { + knSourceParams *types.KnSourceParams + + knSourceClientFunc KnSourceClientFunc +} + +type KnSourceClientFunc = func(knSourceParams *types.KnSourceParams, restConfig *rest.Config, namespace string) types.KnSourceClient + +func NewDefaultKnSourceFactory() types.KnSourceFactory { + return &DefautKnSourceFactory{ + knSourceClientFunc: client.NewKnSourceClient, + } +} + +func (f *DefautKnSourceFactory) CreateKnSourceParams() *types.KnSourceParams { + f.knSourceParams = &types.KnSourceParams{ + SinkFlag: flags.SinkFlags{}, + } + f.knSourceParams.Initialize() + return f.knSourceParams +} + +func (f *DefautKnSourceFactory) CreateKnSourceClient(restConfig *rest.Config, namespace string) types.KnSourceClient { + return f.knSourceClientFunc(f.knSourceParams, restConfig, namespace) +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/rune_factory.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/rune_factory.go new file mode 100644 index 0000000000..57251af81e --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories/rune_factory.go @@ -0,0 +1,133 @@ +// 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 factories + +import ( + "fmt" + + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" + + "github.com/spf13/cobra" +) + +type DefautRunEFactory struct { + knSourceFactory types.KnSourceFactory +} + +func NewDefaultRunEFactory(knSourceFactory types.KnSourceFactory) types.RunEFactory { + return &DefautRunEFactory{ + knSourceFactory: knSourceFactory, + } +} + +func (f *DefautRunEFactory) ListRunE() types.RunE { + return func(cmd *cobra.Command, args []string) error { + namespace, err := f.KnSourceFactory().KnSourceParams().GetNamespace(cmd) + if err != nil { + return err + } + + restConfig, err := f.KnSourceFactory().KnSourceParams().KnParams.RestConfig() + if err != nil { + return err + } + + knSourceClient := f.KnSourceClient(restConfig, namespace) + + fmt.Printf("%s RunE called: args: %#v, client: %#v, sink: %s\n", cmd.Name(), args, knSourceClient, knSourceClient.KnSourceParams().SinkFlag) + + return nil + } +} + +func (f *DefautRunEFactory) CreateRunE() types.RunE { + return func(cmd *cobra.Command, args []string) error { + namespace, err := f.KnSourceFactory().KnSourceParams().GetNamespace(cmd) + if err != nil { + return err + } + + restConfig, err := f.KnSourceFactory().KnSourceParams().KnParams.RestConfig() + if err != nil { + return err + } + + knSourceClient := f.KnSourceClient(restConfig, namespace) + + fmt.Printf("%s RunE called: args: %#v, client: %#v, sink: %s\n", cmd.Name(), args, knSourceClient, knSourceClient.KnSourceParams().SinkFlag) + + return nil + } +} + +func (f *DefautRunEFactory) DeleteRunE() types.RunE { + return func(cmd *cobra.Command, args []string) error { + namespace, err := f.KnSourceFactory().KnSourceParams().GetNamespace(cmd) + if err != nil { + return err + } + + restConfig, err := f.KnSourceFactory().KnSourceParams().KnParams.RestConfig() + if err != nil { + return err + } + + knSourceClient := f.KnSourceClient(restConfig, namespace) + + fmt.Printf("%s RunE called: args: %#v, client: %#v, sink: %s\n", cmd.Name(), args, knSourceClient, knSourceClient.KnSourceParams().SinkFlag) + + return nil + } +} + +func (f *DefautRunEFactory) UpdateRunE() types.RunE { + return func(cmd *cobra.Command, args []string) error { + namespace, err := f.KnSourceFactory().KnSourceParams().GetNamespace(cmd) + if err != nil { + return err + } + + restConfig, err := f.KnSourceFactory().KnSourceParams().KnParams.RestConfig() + if err != nil { + return err + } + + knSourceClient := f.KnSourceClient(restConfig, namespace) + + fmt.Printf("%s RunE called: args: %#v, client: %#v, sink: %s\n", cmd.Name(), args, knSourceClient, knSourceClient.KnSourceParams().SinkFlag) + + return nil + } +} + +func (f *DefautRunEFactory) DescribeRunE() types.RunE { + return func(cmd *cobra.Command, args []string) error { + namespace, err := f.KnSourceFactory().KnSourceParams().GetNamespace(cmd) + if err != nil { + return err + } + + restConfig, err := f.KnSourceFactory().KnSourceParams().KnParams.RestConfig() + if err != nil { + return err + } + + knSourceClient := f.KnSourceClient(restConfig, namespace) + + fmt.Printf("%s RunE called: args: %#v, client: %#v, sink: %s\n", cmd.Name(), args, knSourceClient, knSourceClient.KnSourceParams().SinkFlag) + + return nil + } +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/interfaces.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/interfaces.go new file mode 100644 index 0000000000..a513bb0cd2 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/interfaces.go @@ -0,0 +1,88 @@ +// 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. +// +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate + +package types + +import ( + "github.com/spf13/cobra" + "github.com/spf13/pflag" + + "k8s.io/client-go/rest" +) + +// RunE abstracts the Cobra RunE interface into a usable type +type RunE = func(cmd *cobra.Command, args []string) error + +// KnSourceClient is the base interface for all kn-source-extension +// +//counterfeiter:generate . KnSourceClient +type KnSourceClient interface { + KnSourceParams() *KnSourceParams + Namespace() string + RestConfig() *rest.Config +} + +// KnSourceFactory is the base factory interface for all kn-source-extension factories +// +//counterfeiter:generate . KnSourceFactory +type KnSourceFactory interface { + KnSourceParams() *KnSourceParams + + CreateKnSourceParams() *KnSourceParams + CreateKnSourceClient(restConfig *rest.Config, namespace string) KnSourceClient +} + +// CommandFactory is the factory for cobra.Command objects +// +//counterfeiter:generate . CommandFactory +type CommandFactory interface { + SourceCommand() *cobra.Command + + ListCommand() *cobra.Command + CreateCommand() *cobra.Command + DeleteCommand() *cobra.Command + UpdateCommand() *cobra.Command + DescribeCommand() *cobra.Command + + KnSourceFactory() KnSourceFactory +} + +// FlagsFactory is the factory for pflag.FlagSet objects +// +//counterfeiter:generate . FlagsFactory +type FlagsFactory interface { + ListFlags() *pflag.FlagSet + CreateFlags() *pflag.FlagSet + DeleteFlags() *pflag.FlagSet + UpdateFlags() *pflag.FlagSet + DescribeFlags() *pflag.FlagSet + + KnSourceFactory() KnSourceFactory +} + +// RunEFactory is the factory for RunE objects +// +//counterfeiter:generate . RunEFactory +type RunEFactory interface { + ListRunE() RunE + CreateRunE() RunE + DeleteRunE() RunE + UpdateRunE() RunE + DescribeRunE() RunE + + KnSourceFactory() KnSourceFactory + KnSourceClient(restConfig *rest.Config, namespace string) KnSourceClient +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/structs.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/structs.go new file mode 100644 index 0000000000..9d5236cc92 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/structs.go @@ -0,0 +1,37 @@ +// 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. +// +// go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate + +package types + +import ( + "github.com/spf13/cobra" + "knative.dev/client-pkg/pkg/kn/commands" + "knative.dev/client-pkg/pkg/kn/commands/flags" +) + +type KnSourceParams struct { + commands.KnParams + + SinkFlag flags.SinkFlags +} + +func (p *KnSourceParams) AddCommonFlags(cmd *cobra.Command) { + commands.AddNamespaceFlags(cmd.Flags(), true) +} + +func (p *KnSourceParams) AddCreateUpdateFlags(cmd *cobra.Command) { + p.SinkFlag.Add(cmd) +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_command_factory.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_command_factory.go new file mode 100644 index 0000000000..fefdb93a85 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_command_factory.go @@ -0,0 +1,493 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package typesfakes + +import ( + "sync" + + "github.com/spf13/cobra" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" +) + +type FakeCommandFactory struct { + CreateCommandStub func() *cobra.Command + createCommandMutex sync.RWMutex + createCommandArgsForCall []struct { + } + createCommandReturns struct { + result1 *cobra.Command + } + createCommandReturnsOnCall map[int]struct { + result1 *cobra.Command + } + DeleteCommandStub func() *cobra.Command + deleteCommandMutex sync.RWMutex + deleteCommandArgsForCall []struct { + } + deleteCommandReturns struct { + result1 *cobra.Command + } + deleteCommandReturnsOnCall map[int]struct { + result1 *cobra.Command + } + DescribeCommandStub func() *cobra.Command + describeCommandMutex sync.RWMutex + describeCommandArgsForCall []struct { + } + describeCommandReturns struct { + result1 *cobra.Command + } + describeCommandReturnsOnCall map[int]struct { + result1 *cobra.Command + } + KnSourceFactoryStub func() types.KnSourceFactory + knSourceFactoryMutex sync.RWMutex + knSourceFactoryArgsForCall []struct { + } + knSourceFactoryReturns struct { + result1 types.KnSourceFactory + } + knSourceFactoryReturnsOnCall map[int]struct { + result1 types.KnSourceFactory + } + ListCommandStub func() *cobra.Command + listCommandMutex sync.RWMutex + listCommandArgsForCall []struct { + } + listCommandReturns struct { + result1 *cobra.Command + } + listCommandReturnsOnCall map[int]struct { + result1 *cobra.Command + } + SourceCommandStub func() *cobra.Command + sourceCommandMutex sync.RWMutex + sourceCommandArgsForCall []struct { + } + sourceCommandReturns struct { + result1 *cobra.Command + } + sourceCommandReturnsOnCall map[int]struct { + result1 *cobra.Command + } + UpdateCommandStub func() *cobra.Command + updateCommandMutex sync.RWMutex + updateCommandArgsForCall []struct { + } + updateCommandReturns struct { + result1 *cobra.Command + } + updateCommandReturnsOnCall map[int]struct { + result1 *cobra.Command + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeCommandFactory) CreateCommand() *cobra.Command { + fake.createCommandMutex.Lock() + ret, specificReturn := fake.createCommandReturnsOnCall[len(fake.createCommandArgsForCall)] + fake.createCommandArgsForCall = append(fake.createCommandArgsForCall, struct { + }{}) + stub := fake.CreateCommandStub + fakeReturns := fake.createCommandReturns + fake.recordInvocation("CreateCommand", []interface{}{}) + fake.createCommandMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeCommandFactory) CreateCommandCallCount() int { + fake.createCommandMutex.RLock() + defer fake.createCommandMutex.RUnlock() + return len(fake.createCommandArgsForCall) +} + +func (fake *FakeCommandFactory) CreateCommandCalls(stub func() *cobra.Command) { + fake.createCommandMutex.Lock() + defer fake.createCommandMutex.Unlock() + fake.CreateCommandStub = stub +} + +func (fake *FakeCommandFactory) CreateCommandReturns(result1 *cobra.Command) { + fake.createCommandMutex.Lock() + defer fake.createCommandMutex.Unlock() + fake.CreateCommandStub = nil + fake.createCommandReturns = struct { + result1 *cobra.Command + }{result1} +} + +func (fake *FakeCommandFactory) CreateCommandReturnsOnCall(i int, result1 *cobra.Command) { + fake.createCommandMutex.Lock() + defer fake.createCommandMutex.Unlock() + fake.CreateCommandStub = nil + if fake.createCommandReturnsOnCall == nil { + fake.createCommandReturnsOnCall = make(map[int]struct { + result1 *cobra.Command + }) + } + fake.createCommandReturnsOnCall[i] = struct { + result1 *cobra.Command + }{result1} +} + +func (fake *FakeCommandFactory) DeleteCommand() *cobra.Command { + fake.deleteCommandMutex.Lock() + ret, specificReturn := fake.deleteCommandReturnsOnCall[len(fake.deleteCommandArgsForCall)] + fake.deleteCommandArgsForCall = append(fake.deleteCommandArgsForCall, struct { + }{}) + stub := fake.DeleteCommandStub + fakeReturns := fake.deleteCommandReturns + fake.recordInvocation("DeleteCommand", []interface{}{}) + fake.deleteCommandMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeCommandFactory) DeleteCommandCallCount() int { + fake.deleteCommandMutex.RLock() + defer fake.deleteCommandMutex.RUnlock() + return len(fake.deleteCommandArgsForCall) +} + +func (fake *FakeCommandFactory) DeleteCommandCalls(stub func() *cobra.Command) { + fake.deleteCommandMutex.Lock() + defer fake.deleteCommandMutex.Unlock() + fake.DeleteCommandStub = stub +} + +func (fake *FakeCommandFactory) DeleteCommandReturns(result1 *cobra.Command) { + fake.deleteCommandMutex.Lock() + defer fake.deleteCommandMutex.Unlock() + fake.DeleteCommandStub = nil + fake.deleteCommandReturns = struct { + result1 *cobra.Command + }{result1} +} + +func (fake *FakeCommandFactory) DeleteCommandReturnsOnCall(i int, result1 *cobra.Command) { + fake.deleteCommandMutex.Lock() + defer fake.deleteCommandMutex.Unlock() + fake.DeleteCommandStub = nil + if fake.deleteCommandReturnsOnCall == nil { + fake.deleteCommandReturnsOnCall = make(map[int]struct { + result1 *cobra.Command + }) + } + fake.deleteCommandReturnsOnCall[i] = struct { + result1 *cobra.Command + }{result1} +} + +func (fake *FakeCommandFactory) DescribeCommand() *cobra.Command { + fake.describeCommandMutex.Lock() + ret, specificReturn := fake.describeCommandReturnsOnCall[len(fake.describeCommandArgsForCall)] + fake.describeCommandArgsForCall = append(fake.describeCommandArgsForCall, struct { + }{}) + stub := fake.DescribeCommandStub + fakeReturns := fake.describeCommandReturns + fake.recordInvocation("DescribeCommand", []interface{}{}) + fake.describeCommandMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeCommandFactory) DescribeCommandCallCount() int { + fake.describeCommandMutex.RLock() + defer fake.describeCommandMutex.RUnlock() + return len(fake.describeCommandArgsForCall) +} + +func (fake *FakeCommandFactory) DescribeCommandCalls(stub func() *cobra.Command) { + fake.describeCommandMutex.Lock() + defer fake.describeCommandMutex.Unlock() + fake.DescribeCommandStub = stub +} + +func (fake *FakeCommandFactory) DescribeCommandReturns(result1 *cobra.Command) { + fake.describeCommandMutex.Lock() + defer fake.describeCommandMutex.Unlock() + fake.DescribeCommandStub = nil + fake.describeCommandReturns = struct { + result1 *cobra.Command + }{result1} +} + +func (fake *FakeCommandFactory) DescribeCommandReturnsOnCall(i int, result1 *cobra.Command) { + fake.describeCommandMutex.Lock() + defer fake.describeCommandMutex.Unlock() + fake.DescribeCommandStub = nil + if fake.describeCommandReturnsOnCall == nil { + fake.describeCommandReturnsOnCall = make(map[int]struct { + result1 *cobra.Command + }) + } + fake.describeCommandReturnsOnCall[i] = struct { + result1 *cobra.Command + }{result1} +} + +func (fake *FakeCommandFactory) KnSourceFactory() types.KnSourceFactory { + fake.knSourceFactoryMutex.Lock() + ret, specificReturn := fake.knSourceFactoryReturnsOnCall[len(fake.knSourceFactoryArgsForCall)] + fake.knSourceFactoryArgsForCall = append(fake.knSourceFactoryArgsForCall, struct { + }{}) + stub := fake.KnSourceFactoryStub + fakeReturns := fake.knSourceFactoryReturns + fake.recordInvocation("KnSourceFactory", []interface{}{}) + fake.knSourceFactoryMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeCommandFactory) KnSourceFactoryCallCount() int { + fake.knSourceFactoryMutex.RLock() + defer fake.knSourceFactoryMutex.RUnlock() + return len(fake.knSourceFactoryArgsForCall) +} + +func (fake *FakeCommandFactory) KnSourceFactoryCalls(stub func() types.KnSourceFactory) { + fake.knSourceFactoryMutex.Lock() + defer fake.knSourceFactoryMutex.Unlock() + fake.KnSourceFactoryStub = stub +} + +func (fake *FakeCommandFactory) KnSourceFactoryReturns(result1 types.KnSourceFactory) { + fake.knSourceFactoryMutex.Lock() + defer fake.knSourceFactoryMutex.Unlock() + fake.KnSourceFactoryStub = nil + fake.knSourceFactoryReturns = struct { + result1 types.KnSourceFactory + }{result1} +} + +func (fake *FakeCommandFactory) KnSourceFactoryReturnsOnCall(i int, result1 types.KnSourceFactory) { + fake.knSourceFactoryMutex.Lock() + defer fake.knSourceFactoryMutex.Unlock() + fake.KnSourceFactoryStub = nil + if fake.knSourceFactoryReturnsOnCall == nil { + fake.knSourceFactoryReturnsOnCall = make(map[int]struct { + result1 types.KnSourceFactory + }) + } + fake.knSourceFactoryReturnsOnCall[i] = struct { + result1 types.KnSourceFactory + }{result1} +} + +func (fake *FakeCommandFactory) ListCommand() *cobra.Command { + fake.listCommandMutex.Lock() + ret, specificReturn := fake.listCommandReturnsOnCall[len(fake.listCommandArgsForCall)] + fake.listCommandArgsForCall = append(fake.listCommandArgsForCall, struct { + }{}) + stub := fake.ListCommandStub + fakeReturns := fake.listCommandReturns + fake.recordInvocation("ListCommand", []interface{}{}) + fake.listCommandMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeCommandFactory) ListCommandCallCount() int { + fake.listCommandMutex.RLock() + defer fake.listCommandMutex.RUnlock() + return len(fake.listCommandArgsForCall) +} + +func (fake *FakeCommandFactory) ListCommandCalls(stub func() *cobra.Command) { + fake.listCommandMutex.Lock() + defer fake.listCommandMutex.Unlock() + fake.ListCommandStub = stub +} + +func (fake *FakeCommandFactory) ListCommandReturns(result1 *cobra.Command) { + fake.listCommandMutex.Lock() + defer fake.listCommandMutex.Unlock() + fake.ListCommandStub = nil + fake.listCommandReturns = struct { + result1 *cobra.Command + }{result1} +} + +func (fake *FakeCommandFactory) ListCommandReturnsOnCall(i int, result1 *cobra.Command) { + fake.listCommandMutex.Lock() + defer fake.listCommandMutex.Unlock() + fake.ListCommandStub = nil + if fake.listCommandReturnsOnCall == nil { + fake.listCommandReturnsOnCall = make(map[int]struct { + result1 *cobra.Command + }) + } + fake.listCommandReturnsOnCall[i] = struct { + result1 *cobra.Command + }{result1} +} + +func (fake *FakeCommandFactory) SourceCommand() *cobra.Command { + fake.sourceCommandMutex.Lock() + ret, specificReturn := fake.sourceCommandReturnsOnCall[len(fake.sourceCommandArgsForCall)] + fake.sourceCommandArgsForCall = append(fake.sourceCommandArgsForCall, struct { + }{}) + stub := fake.SourceCommandStub + fakeReturns := fake.sourceCommandReturns + fake.recordInvocation("SourceCommand", []interface{}{}) + fake.sourceCommandMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeCommandFactory) SourceCommandCallCount() int { + fake.sourceCommandMutex.RLock() + defer fake.sourceCommandMutex.RUnlock() + return len(fake.sourceCommandArgsForCall) +} + +func (fake *FakeCommandFactory) SourceCommandCalls(stub func() *cobra.Command) { + fake.sourceCommandMutex.Lock() + defer fake.sourceCommandMutex.Unlock() + fake.SourceCommandStub = stub +} + +func (fake *FakeCommandFactory) SourceCommandReturns(result1 *cobra.Command) { + fake.sourceCommandMutex.Lock() + defer fake.sourceCommandMutex.Unlock() + fake.SourceCommandStub = nil + fake.sourceCommandReturns = struct { + result1 *cobra.Command + }{result1} +} + +func (fake *FakeCommandFactory) SourceCommandReturnsOnCall(i int, result1 *cobra.Command) { + fake.sourceCommandMutex.Lock() + defer fake.sourceCommandMutex.Unlock() + fake.SourceCommandStub = nil + if fake.sourceCommandReturnsOnCall == nil { + fake.sourceCommandReturnsOnCall = make(map[int]struct { + result1 *cobra.Command + }) + } + fake.sourceCommandReturnsOnCall[i] = struct { + result1 *cobra.Command + }{result1} +} + +func (fake *FakeCommandFactory) UpdateCommand() *cobra.Command { + fake.updateCommandMutex.Lock() + ret, specificReturn := fake.updateCommandReturnsOnCall[len(fake.updateCommandArgsForCall)] + fake.updateCommandArgsForCall = append(fake.updateCommandArgsForCall, struct { + }{}) + stub := fake.UpdateCommandStub + fakeReturns := fake.updateCommandReturns + fake.recordInvocation("UpdateCommand", []interface{}{}) + fake.updateCommandMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeCommandFactory) UpdateCommandCallCount() int { + fake.updateCommandMutex.RLock() + defer fake.updateCommandMutex.RUnlock() + return len(fake.updateCommandArgsForCall) +} + +func (fake *FakeCommandFactory) UpdateCommandCalls(stub func() *cobra.Command) { + fake.updateCommandMutex.Lock() + defer fake.updateCommandMutex.Unlock() + fake.UpdateCommandStub = stub +} + +func (fake *FakeCommandFactory) UpdateCommandReturns(result1 *cobra.Command) { + fake.updateCommandMutex.Lock() + defer fake.updateCommandMutex.Unlock() + fake.UpdateCommandStub = nil + fake.updateCommandReturns = struct { + result1 *cobra.Command + }{result1} +} + +func (fake *FakeCommandFactory) UpdateCommandReturnsOnCall(i int, result1 *cobra.Command) { + fake.updateCommandMutex.Lock() + defer fake.updateCommandMutex.Unlock() + fake.UpdateCommandStub = nil + if fake.updateCommandReturnsOnCall == nil { + fake.updateCommandReturnsOnCall = make(map[int]struct { + result1 *cobra.Command + }) + } + fake.updateCommandReturnsOnCall[i] = struct { + result1 *cobra.Command + }{result1} +} + +func (fake *FakeCommandFactory) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.createCommandMutex.RLock() + defer fake.createCommandMutex.RUnlock() + fake.deleteCommandMutex.RLock() + defer fake.deleteCommandMutex.RUnlock() + fake.describeCommandMutex.RLock() + defer fake.describeCommandMutex.RUnlock() + fake.knSourceFactoryMutex.RLock() + defer fake.knSourceFactoryMutex.RUnlock() + fake.listCommandMutex.RLock() + defer fake.listCommandMutex.RUnlock() + fake.sourceCommandMutex.RLock() + defer fake.sourceCommandMutex.RUnlock() + fake.updateCommandMutex.RLock() + defer fake.updateCommandMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeCommandFactory) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ types.CommandFactory = new(FakeCommandFactory) diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_flags_factory.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_flags_factory.go new file mode 100644 index 0000000000..eb2a5bc78e --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_flags_factory.go @@ -0,0 +1,428 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package typesfakes + +import ( + "sync" + + "github.com/spf13/pflag" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" +) + +type FakeFlagsFactory struct { + CreateFlagsStub func() *pflag.FlagSet + createFlagsMutex sync.RWMutex + createFlagsArgsForCall []struct { + } + createFlagsReturns struct { + result1 *pflag.FlagSet + } + createFlagsReturnsOnCall map[int]struct { + result1 *pflag.FlagSet + } + DeleteFlagsStub func() *pflag.FlagSet + deleteFlagsMutex sync.RWMutex + deleteFlagsArgsForCall []struct { + } + deleteFlagsReturns struct { + result1 *pflag.FlagSet + } + deleteFlagsReturnsOnCall map[int]struct { + result1 *pflag.FlagSet + } + DescribeFlagsStub func() *pflag.FlagSet + describeFlagsMutex sync.RWMutex + describeFlagsArgsForCall []struct { + } + describeFlagsReturns struct { + result1 *pflag.FlagSet + } + describeFlagsReturnsOnCall map[int]struct { + result1 *pflag.FlagSet + } + KnSourceFactoryStub func() types.KnSourceFactory + knSourceFactoryMutex sync.RWMutex + knSourceFactoryArgsForCall []struct { + } + knSourceFactoryReturns struct { + result1 types.KnSourceFactory + } + knSourceFactoryReturnsOnCall map[int]struct { + result1 types.KnSourceFactory + } + ListFlagsStub func() *pflag.FlagSet + listFlagsMutex sync.RWMutex + listFlagsArgsForCall []struct { + } + listFlagsReturns struct { + result1 *pflag.FlagSet + } + listFlagsReturnsOnCall map[int]struct { + result1 *pflag.FlagSet + } + UpdateFlagsStub func() *pflag.FlagSet + updateFlagsMutex sync.RWMutex + updateFlagsArgsForCall []struct { + } + updateFlagsReturns struct { + result1 *pflag.FlagSet + } + updateFlagsReturnsOnCall map[int]struct { + result1 *pflag.FlagSet + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeFlagsFactory) CreateFlags() *pflag.FlagSet { + fake.createFlagsMutex.Lock() + ret, specificReturn := fake.createFlagsReturnsOnCall[len(fake.createFlagsArgsForCall)] + fake.createFlagsArgsForCall = append(fake.createFlagsArgsForCall, struct { + }{}) + stub := fake.CreateFlagsStub + fakeReturns := fake.createFlagsReturns + fake.recordInvocation("CreateFlags", []interface{}{}) + fake.createFlagsMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeFlagsFactory) CreateFlagsCallCount() int { + fake.createFlagsMutex.RLock() + defer fake.createFlagsMutex.RUnlock() + return len(fake.createFlagsArgsForCall) +} + +func (fake *FakeFlagsFactory) CreateFlagsCalls(stub func() *pflag.FlagSet) { + fake.createFlagsMutex.Lock() + defer fake.createFlagsMutex.Unlock() + fake.CreateFlagsStub = stub +} + +func (fake *FakeFlagsFactory) CreateFlagsReturns(result1 *pflag.FlagSet) { + fake.createFlagsMutex.Lock() + defer fake.createFlagsMutex.Unlock() + fake.CreateFlagsStub = nil + fake.createFlagsReturns = struct { + result1 *pflag.FlagSet + }{result1} +} + +func (fake *FakeFlagsFactory) CreateFlagsReturnsOnCall(i int, result1 *pflag.FlagSet) { + fake.createFlagsMutex.Lock() + defer fake.createFlagsMutex.Unlock() + fake.CreateFlagsStub = nil + if fake.createFlagsReturnsOnCall == nil { + fake.createFlagsReturnsOnCall = make(map[int]struct { + result1 *pflag.FlagSet + }) + } + fake.createFlagsReturnsOnCall[i] = struct { + result1 *pflag.FlagSet + }{result1} +} + +func (fake *FakeFlagsFactory) DeleteFlags() *pflag.FlagSet { + fake.deleteFlagsMutex.Lock() + ret, specificReturn := fake.deleteFlagsReturnsOnCall[len(fake.deleteFlagsArgsForCall)] + fake.deleteFlagsArgsForCall = append(fake.deleteFlagsArgsForCall, struct { + }{}) + stub := fake.DeleteFlagsStub + fakeReturns := fake.deleteFlagsReturns + fake.recordInvocation("DeleteFlags", []interface{}{}) + fake.deleteFlagsMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeFlagsFactory) DeleteFlagsCallCount() int { + fake.deleteFlagsMutex.RLock() + defer fake.deleteFlagsMutex.RUnlock() + return len(fake.deleteFlagsArgsForCall) +} + +func (fake *FakeFlagsFactory) DeleteFlagsCalls(stub func() *pflag.FlagSet) { + fake.deleteFlagsMutex.Lock() + defer fake.deleteFlagsMutex.Unlock() + fake.DeleteFlagsStub = stub +} + +func (fake *FakeFlagsFactory) DeleteFlagsReturns(result1 *pflag.FlagSet) { + fake.deleteFlagsMutex.Lock() + defer fake.deleteFlagsMutex.Unlock() + fake.DeleteFlagsStub = nil + fake.deleteFlagsReturns = struct { + result1 *pflag.FlagSet + }{result1} +} + +func (fake *FakeFlagsFactory) DeleteFlagsReturnsOnCall(i int, result1 *pflag.FlagSet) { + fake.deleteFlagsMutex.Lock() + defer fake.deleteFlagsMutex.Unlock() + fake.DeleteFlagsStub = nil + if fake.deleteFlagsReturnsOnCall == nil { + fake.deleteFlagsReturnsOnCall = make(map[int]struct { + result1 *pflag.FlagSet + }) + } + fake.deleteFlagsReturnsOnCall[i] = struct { + result1 *pflag.FlagSet + }{result1} +} + +func (fake *FakeFlagsFactory) DescribeFlags() *pflag.FlagSet { + fake.describeFlagsMutex.Lock() + ret, specificReturn := fake.describeFlagsReturnsOnCall[len(fake.describeFlagsArgsForCall)] + fake.describeFlagsArgsForCall = append(fake.describeFlagsArgsForCall, struct { + }{}) + stub := fake.DescribeFlagsStub + fakeReturns := fake.describeFlagsReturns + fake.recordInvocation("DescribeFlags", []interface{}{}) + fake.describeFlagsMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeFlagsFactory) DescribeFlagsCallCount() int { + fake.describeFlagsMutex.RLock() + defer fake.describeFlagsMutex.RUnlock() + return len(fake.describeFlagsArgsForCall) +} + +func (fake *FakeFlagsFactory) DescribeFlagsCalls(stub func() *pflag.FlagSet) { + fake.describeFlagsMutex.Lock() + defer fake.describeFlagsMutex.Unlock() + fake.DescribeFlagsStub = stub +} + +func (fake *FakeFlagsFactory) DescribeFlagsReturns(result1 *pflag.FlagSet) { + fake.describeFlagsMutex.Lock() + defer fake.describeFlagsMutex.Unlock() + fake.DescribeFlagsStub = nil + fake.describeFlagsReturns = struct { + result1 *pflag.FlagSet + }{result1} +} + +func (fake *FakeFlagsFactory) DescribeFlagsReturnsOnCall(i int, result1 *pflag.FlagSet) { + fake.describeFlagsMutex.Lock() + defer fake.describeFlagsMutex.Unlock() + fake.DescribeFlagsStub = nil + if fake.describeFlagsReturnsOnCall == nil { + fake.describeFlagsReturnsOnCall = make(map[int]struct { + result1 *pflag.FlagSet + }) + } + fake.describeFlagsReturnsOnCall[i] = struct { + result1 *pflag.FlagSet + }{result1} +} + +func (fake *FakeFlagsFactory) KnSourceFactory() types.KnSourceFactory { + fake.knSourceFactoryMutex.Lock() + ret, specificReturn := fake.knSourceFactoryReturnsOnCall[len(fake.knSourceFactoryArgsForCall)] + fake.knSourceFactoryArgsForCall = append(fake.knSourceFactoryArgsForCall, struct { + }{}) + stub := fake.KnSourceFactoryStub + fakeReturns := fake.knSourceFactoryReturns + fake.recordInvocation("KnSourceFactory", []interface{}{}) + fake.knSourceFactoryMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeFlagsFactory) KnSourceFactoryCallCount() int { + fake.knSourceFactoryMutex.RLock() + defer fake.knSourceFactoryMutex.RUnlock() + return len(fake.knSourceFactoryArgsForCall) +} + +func (fake *FakeFlagsFactory) KnSourceFactoryCalls(stub func() types.KnSourceFactory) { + fake.knSourceFactoryMutex.Lock() + defer fake.knSourceFactoryMutex.Unlock() + fake.KnSourceFactoryStub = stub +} + +func (fake *FakeFlagsFactory) KnSourceFactoryReturns(result1 types.KnSourceFactory) { + fake.knSourceFactoryMutex.Lock() + defer fake.knSourceFactoryMutex.Unlock() + fake.KnSourceFactoryStub = nil + fake.knSourceFactoryReturns = struct { + result1 types.KnSourceFactory + }{result1} +} + +func (fake *FakeFlagsFactory) KnSourceFactoryReturnsOnCall(i int, result1 types.KnSourceFactory) { + fake.knSourceFactoryMutex.Lock() + defer fake.knSourceFactoryMutex.Unlock() + fake.KnSourceFactoryStub = nil + if fake.knSourceFactoryReturnsOnCall == nil { + fake.knSourceFactoryReturnsOnCall = make(map[int]struct { + result1 types.KnSourceFactory + }) + } + fake.knSourceFactoryReturnsOnCall[i] = struct { + result1 types.KnSourceFactory + }{result1} +} + +func (fake *FakeFlagsFactory) ListFlags() *pflag.FlagSet { + fake.listFlagsMutex.Lock() + ret, specificReturn := fake.listFlagsReturnsOnCall[len(fake.listFlagsArgsForCall)] + fake.listFlagsArgsForCall = append(fake.listFlagsArgsForCall, struct { + }{}) + stub := fake.ListFlagsStub + fakeReturns := fake.listFlagsReturns + fake.recordInvocation("ListFlags", []interface{}{}) + fake.listFlagsMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeFlagsFactory) ListFlagsCallCount() int { + fake.listFlagsMutex.RLock() + defer fake.listFlagsMutex.RUnlock() + return len(fake.listFlagsArgsForCall) +} + +func (fake *FakeFlagsFactory) ListFlagsCalls(stub func() *pflag.FlagSet) { + fake.listFlagsMutex.Lock() + defer fake.listFlagsMutex.Unlock() + fake.ListFlagsStub = stub +} + +func (fake *FakeFlagsFactory) ListFlagsReturns(result1 *pflag.FlagSet) { + fake.listFlagsMutex.Lock() + defer fake.listFlagsMutex.Unlock() + fake.ListFlagsStub = nil + fake.listFlagsReturns = struct { + result1 *pflag.FlagSet + }{result1} +} + +func (fake *FakeFlagsFactory) ListFlagsReturnsOnCall(i int, result1 *pflag.FlagSet) { + fake.listFlagsMutex.Lock() + defer fake.listFlagsMutex.Unlock() + fake.ListFlagsStub = nil + if fake.listFlagsReturnsOnCall == nil { + fake.listFlagsReturnsOnCall = make(map[int]struct { + result1 *pflag.FlagSet + }) + } + fake.listFlagsReturnsOnCall[i] = struct { + result1 *pflag.FlagSet + }{result1} +} + +func (fake *FakeFlagsFactory) UpdateFlags() *pflag.FlagSet { + fake.updateFlagsMutex.Lock() + ret, specificReturn := fake.updateFlagsReturnsOnCall[len(fake.updateFlagsArgsForCall)] + fake.updateFlagsArgsForCall = append(fake.updateFlagsArgsForCall, struct { + }{}) + stub := fake.UpdateFlagsStub + fakeReturns := fake.updateFlagsReturns + fake.recordInvocation("UpdateFlags", []interface{}{}) + fake.updateFlagsMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeFlagsFactory) UpdateFlagsCallCount() int { + fake.updateFlagsMutex.RLock() + defer fake.updateFlagsMutex.RUnlock() + return len(fake.updateFlagsArgsForCall) +} + +func (fake *FakeFlagsFactory) UpdateFlagsCalls(stub func() *pflag.FlagSet) { + fake.updateFlagsMutex.Lock() + defer fake.updateFlagsMutex.Unlock() + fake.UpdateFlagsStub = stub +} + +func (fake *FakeFlagsFactory) UpdateFlagsReturns(result1 *pflag.FlagSet) { + fake.updateFlagsMutex.Lock() + defer fake.updateFlagsMutex.Unlock() + fake.UpdateFlagsStub = nil + fake.updateFlagsReturns = struct { + result1 *pflag.FlagSet + }{result1} +} + +func (fake *FakeFlagsFactory) UpdateFlagsReturnsOnCall(i int, result1 *pflag.FlagSet) { + fake.updateFlagsMutex.Lock() + defer fake.updateFlagsMutex.Unlock() + fake.UpdateFlagsStub = nil + if fake.updateFlagsReturnsOnCall == nil { + fake.updateFlagsReturnsOnCall = make(map[int]struct { + result1 *pflag.FlagSet + }) + } + fake.updateFlagsReturnsOnCall[i] = struct { + result1 *pflag.FlagSet + }{result1} +} + +func (fake *FakeFlagsFactory) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.createFlagsMutex.RLock() + defer fake.createFlagsMutex.RUnlock() + fake.deleteFlagsMutex.RLock() + defer fake.deleteFlagsMutex.RUnlock() + fake.describeFlagsMutex.RLock() + defer fake.describeFlagsMutex.RUnlock() + fake.knSourceFactoryMutex.RLock() + defer fake.knSourceFactoryMutex.RUnlock() + fake.listFlagsMutex.RLock() + defer fake.listFlagsMutex.RUnlock() + fake.updateFlagsMutex.RLock() + defer fake.updateFlagsMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeFlagsFactory) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ types.FlagsFactory = new(FakeFlagsFactory) diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_kn_source_client.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_kn_source_client.go new file mode 100644 index 0000000000..788a5e5479 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_kn_source_client.go @@ -0,0 +1,233 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package typesfakes + +import ( + "sync" + + "k8s.io/client-go/rest" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" +) + +type FakeKnSourceClient struct { + KnSourceParamsStub func() *types.KnSourceParams + knSourceParamsMutex sync.RWMutex + knSourceParamsArgsForCall []struct { + } + knSourceParamsReturns struct { + result1 *types.KnSourceParams + } + knSourceParamsReturnsOnCall map[int]struct { + result1 *types.KnSourceParams + } + NamespaceStub func() string + namespaceMutex sync.RWMutex + namespaceArgsForCall []struct { + } + namespaceReturns struct { + result1 string + } + namespaceReturnsOnCall map[int]struct { + result1 string + } + RestConfigStub func() *rest.Config + restConfigMutex sync.RWMutex + restConfigArgsForCall []struct { + } + restConfigReturns struct { + result1 *rest.Config + } + restConfigReturnsOnCall map[int]struct { + result1 *rest.Config + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeKnSourceClient) KnSourceParams() *types.KnSourceParams { + fake.knSourceParamsMutex.Lock() + ret, specificReturn := fake.knSourceParamsReturnsOnCall[len(fake.knSourceParamsArgsForCall)] + fake.knSourceParamsArgsForCall = append(fake.knSourceParamsArgsForCall, struct { + }{}) + stub := fake.KnSourceParamsStub + fakeReturns := fake.knSourceParamsReturns + fake.recordInvocation("KnSourceParams", []interface{}{}) + fake.knSourceParamsMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeKnSourceClient) KnSourceParamsCallCount() int { + fake.knSourceParamsMutex.RLock() + defer fake.knSourceParamsMutex.RUnlock() + return len(fake.knSourceParamsArgsForCall) +} + +func (fake *FakeKnSourceClient) KnSourceParamsCalls(stub func() *types.KnSourceParams) { + fake.knSourceParamsMutex.Lock() + defer fake.knSourceParamsMutex.Unlock() + fake.KnSourceParamsStub = stub +} + +func (fake *FakeKnSourceClient) KnSourceParamsReturns(result1 *types.KnSourceParams) { + fake.knSourceParamsMutex.Lock() + defer fake.knSourceParamsMutex.Unlock() + fake.KnSourceParamsStub = nil + fake.knSourceParamsReturns = struct { + result1 *types.KnSourceParams + }{result1} +} + +func (fake *FakeKnSourceClient) KnSourceParamsReturnsOnCall(i int, result1 *types.KnSourceParams) { + fake.knSourceParamsMutex.Lock() + defer fake.knSourceParamsMutex.Unlock() + fake.KnSourceParamsStub = nil + if fake.knSourceParamsReturnsOnCall == nil { + fake.knSourceParamsReturnsOnCall = make(map[int]struct { + result1 *types.KnSourceParams + }) + } + fake.knSourceParamsReturnsOnCall[i] = struct { + result1 *types.KnSourceParams + }{result1} +} + +func (fake *FakeKnSourceClient) Namespace() string { + fake.namespaceMutex.Lock() + ret, specificReturn := fake.namespaceReturnsOnCall[len(fake.namespaceArgsForCall)] + fake.namespaceArgsForCall = append(fake.namespaceArgsForCall, struct { + }{}) + stub := fake.NamespaceStub + fakeReturns := fake.namespaceReturns + fake.recordInvocation("Namespace", []interface{}{}) + fake.namespaceMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeKnSourceClient) NamespaceCallCount() int { + fake.namespaceMutex.RLock() + defer fake.namespaceMutex.RUnlock() + return len(fake.namespaceArgsForCall) +} + +func (fake *FakeKnSourceClient) NamespaceCalls(stub func() string) { + fake.namespaceMutex.Lock() + defer fake.namespaceMutex.Unlock() + fake.NamespaceStub = stub +} + +func (fake *FakeKnSourceClient) NamespaceReturns(result1 string) { + fake.namespaceMutex.Lock() + defer fake.namespaceMutex.Unlock() + fake.NamespaceStub = nil + fake.namespaceReturns = struct { + result1 string + }{result1} +} + +func (fake *FakeKnSourceClient) NamespaceReturnsOnCall(i int, result1 string) { + fake.namespaceMutex.Lock() + defer fake.namespaceMutex.Unlock() + fake.NamespaceStub = nil + if fake.namespaceReturnsOnCall == nil { + fake.namespaceReturnsOnCall = make(map[int]struct { + result1 string + }) + } + fake.namespaceReturnsOnCall[i] = struct { + result1 string + }{result1} +} + +func (fake *FakeKnSourceClient) RestConfig() *rest.Config { + fake.restConfigMutex.Lock() + ret, specificReturn := fake.restConfigReturnsOnCall[len(fake.restConfigArgsForCall)] + fake.restConfigArgsForCall = append(fake.restConfigArgsForCall, struct { + }{}) + stub := fake.RestConfigStub + fakeReturns := fake.restConfigReturns + fake.recordInvocation("RestConfig", []interface{}{}) + fake.restConfigMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeKnSourceClient) RestConfigCallCount() int { + fake.restConfigMutex.RLock() + defer fake.restConfigMutex.RUnlock() + return len(fake.restConfigArgsForCall) +} + +func (fake *FakeKnSourceClient) RestConfigCalls(stub func() *rest.Config) { + fake.restConfigMutex.Lock() + defer fake.restConfigMutex.Unlock() + fake.RestConfigStub = stub +} + +func (fake *FakeKnSourceClient) RestConfigReturns(result1 *rest.Config) { + fake.restConfigMutex.Lock() + defer fake.restConfigMutex.Unlock() + fake.RestConfigStub = nil + fake.restConfigReturns = struct { + result1 *rest.Config + }{result1} +} + +func (fake *FakeKnSourceClient) RestConfigReturnsOnCall(i int, result1 *rest.Config) { + fake.restConfigMutex.Lock() + defer fake.restConfigMutex.Unlock() + fake.RestConfigStub = nil + if fake.restConfigReturnsOnCall == nil { + fake.restConfigReturnsOnCall = make(map[int]struct { + result1 *rest.Config + }) + } + fake.restConfigReturnsOnCall[i] = struct { + result1 *rest.Config + }{result1} +} + +func (fake *FakeKnSourceClient) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.knSourceParamsMutex.RLock() + defer fake.knSourceParamsMutex.RUnlock() + fake.namespaceMutex.RLock() + defer fake.namespaceMutex.RUnlock() + fake.restConfigMutex.RLock() + defer fake.restConfigMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeKnSourceClient) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ types.KnSourceClient = new(FakeKnSourceClient) diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_kn_source_factory.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_kn_source_factory.go new file mode 100644 index 0000000000..af08089da6 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_kn_source_factory.go @@ -0,0 +1,244 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package typesfakes + +import ( + "sync" + + "k8s.io/client-go/rest" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" +) + +type FakeKnSourceFactory struct { + CreateKnSourceClientStub func(*rest.Config, string) types.KnSourceClient + createKnSourceClientMutex sync.RWMutex + createKnSourceClientArgsForCall []struct { + arg1 *rest.Config + arg2 string + } + createKnSourceClientReturns struct { + result1 types.KnSourceClient + } + createKnSourceClientReturnsOnCall map[int]struct { + result1 types.KnSourceClient + } + CreateKnSourceParamsStub func() *types.KnSourceParams + createKnSourceParamsMutex sync.RWMutex + createKnSourceParamsArgsForCall []struct { + } + createKnSourceParamsReturns struct { + result1 *types.KnSourceParams + } + createKnSourceParamsReturnsOnCall map[int]struct { + result1 *types.KnSourceParams + } + KnSourceParamsStub func() *types.KnSourceParams + knSourceParamsMutex sync.RWMutex + knSourceParamsArgsForCall []struct { + } + knSourceParamsReturns struct { + result1 *types.KnSourceParams + } + knSourceParamsReturnsOnCall map[int]struct { + result1 *types.KnSourceParams + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeKnSourceFactory) CreateKnSourceClient(arg1 *rest.Config, arg2 string) types.KnSourceClient { + fake.createKnSourceClientMutex.Lock() + ret, specificReturn := fake.createKnSourceClientReturnsOnCall[len(fake.createKnSourceClientArgsForCall)] + fake.createKnSourceClientArgsForCall = append(fake.createKnSourceClientArgsForCall, struct { + arg1 *rest.Config + arg2 string + }{arg1, arg2}) + stub := fake.CreateKnSourceClientStub + fakeReturns := fake.createKnSourceClientReturns + fake.recordInvocation("CreateKnSourceClient", []interface{}{arg1, arg2}) + fake.createKnSourceClientMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeKnSourceFactory) CreateKnSourceClientCallCount() int { + fake.createKnSourceClientMutex.RLock() + defer fake.createKnSourceClientMutex.RUnlock() + return len(fake.createKnSourceClientArgsForCall) +} + +func (fake *FakeKnSourceFactory) CreateKnSourceClientCalls(stub func(*rest.Config, string) types.KnSourceClient) { + fake.createKnSourceClientMutex.Lock() + defer fake.createKnSourceClientMutex.Unlock() + fake.CreateKnSourceClientStub = stub +} + +func (fake *FakeKnSourceFactory) CreateKnSourceClientArgsForCall(i int) (*rest.Config, string) { + fake.createKnSourceClientMutex.RLock() + defer fake.createKnSourceClientMutex.RUnlock() + argsForCall := fake.createKnSourceClientArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakeKnSourceFactory) CreateKnSourceClientReturns(result1 types.KnSourceClient) { + fake.createKnSourceClientMutex.Lock() + defer fake.createKnSourceClientMutex.Unlock() + fake.CreateKnSourceClientStub = nil + fake.createKnSourceClientReturns = struct { + result1 types.KnSourceClient + }{result1} +} + +func (fake *FakeKnSourceFactory) CreateKnSourceClientReturnsOnCall(i int, result1 types.KnSourceClient) { + fake.createKnSourceClientMutex.Lock() + defer fake.createKnSourceClientMutex.Unlock() + fake.CreateKnSourceClientStub = nil + if fake.createKnSourceClientReturnsOnCall == nil { + fake.createKnSourceClientReturnsOnCall = make(map[int]struct { + result1 types.KnSourceClient + }) + } + fake.createKnSourceClientReturnsOnCall[i] = struct { + result1 types.KnSourceClient + }{result1} +} + +func (fake *FakeKnSourceFactory) CreateKnSourceParams() *types.KnSourceParams { + fake.createKnSourceParamsMutex.Lock() + ret, specificReturn := fake.createKnSourceParamsReturnsOnCall[len(fake.createKnSourceParamsArgsForCall)] + fake.createKnSourceParamsArgsForCall = append(fake.createKnSourceParamsArgsForCall, struct { + }{}) + stub := fake.CreateKnSourceParamsStub + fakeReturns := fake.createKnSourceParamsReturns + fake.recordInvocation("CreateKnSourceParams", []interface{}{}) + fake.createKnSourceParamsMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeKnSourceFactory) CreateKnSourceParamsCallCount() int { + fake.createKnSourceParamsMutex.RLock() + defer fake.createKnSourceParamsMutex.RUnlock() + return len(fake.createKnSourceParamsArgsForCall) +} + +func (fake *FakeKnSourceFactory) CreateKnSourceParamsCalls(stub func() *types.KnSourceParams) { + fake.createKnSourceParamsMutex.Lock() + defer fake.createKnSourceParamsMutex.Unlock() + fake.CreateKnSourceParamsStub = stub +} + +func (fake *FakeKnSourceFactory) CreateKnSourceParamsReturns(result1 *types.KnSourceParams) { + fake.createKnSourceParamsMutex.Lock() + defer fake.createKnSourceParamsMutex.Unlock() + fake.CreateKnSourceParamsStub = nil + fake.createKnSourceParamsReturns = struct { + result1 *types.KnSourceParams + }{result1} +} + +func (fake *FakeKnSourceFactory) CreateKnSourceParamsReturnsOnCall(i int, result1 *types.KnSourceParams) { + fake.createKnSourceParamsMutex.Lock() + defer fake.createKnSourceParamsMutex.Unlock() + fake.CreateKnSourceParamsStub = nil + if fake.createKnSourceParamsReturnsOnCall == nil { + fake.createKnSourceParamsReturnsOnCall = make(map[int]struct { + result1 *types.KnSourceParams + }) + } + fake.createKnSourceParamsReturnsOnCall[i] = struct { + result1 *types.KnSourceParams + }{result1} +} + +func (fake *FakeKnSourceFactory) KnSourceParams() *types.KnSourceParams { + fake.knSourceParamsMutex.Lock() + ret, specificReturn := fake.knSourceParamsReturnsOnCall[len(fake.knSourceParamsArgsForCall)] + fake.knSourceParamsArgsForCall = append(fake.knSourceParamsArgsForCall, struct { + }{}) + stub := fake.KnSourceParamsStub + fakeReturns := fake.knSourceParamsReturns + fake.recordInvocation("KnSourceParams", []interface{}{}) + fake.knSourceParamsMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeKnSourceFactory) KnSourceParamsCallCount() int { + fake.knSourceParamsMutex.RLock() + defer fake.knSourceParamsMutex.RUnlock() + return len(fake.knSourceParamsArgsForCall) +} + +func (fake *FakeKnSourceFactory) KnSourceParamsCalls(stub func() *types.KnSourceParams) { + fake.knSourceParamsMutex.Lock() + defer fake.knSourceParamsMutex.Unlock() + fake.KnSourceParamsStub = stub +} + +func (fake *FakeKnSourceFactory) KnSourceParamsReturns(result1 *types.KnSourceParams) { + fake.knSourceParamsMutex.Lock() + defer fake.knSourceParamsMutex.Unlock() + fake.KnSourceParamsStub = nil + fake.knSourceParamsReturns = struct { + result1 *types.KnSourceParams + }{result1} +} + +func (fake *FakeKnSourceFactory) KnSourceParamsReturnsOnCall(i int, result1 *types.KnSourceParams) { + fake.knSourceParamsMutex.Lock() + defer fake.knSourceParamsMutex.Unlock() + fake.KnSourceParamsStub = nil + if fake.knSourceParamsReturnsOnCall == nil { + fake.knSourceParamsReturnsOnCall = make(map[int]struct { + result1 *types.KnSourceParams + }) + } + fake.knSourceParamsReturnsOnCall[i] = struct { + result1 *types.KnSourceParams + }{result1} +} + +func (fake *FakeKnSourceFactory) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.createKnSourceClientMutex.RLock() + defer fake.createKnSourceClientMutex.RUnlock() + fake.createKnSourceParamsMutex.RLock() + defer fake.createKnSourceParamsMutex.RUnlock() + fake.knSourceParamsMutex.RLock() + defer fake.knSourceParamsMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeKnSourceFactory) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ types.KnSourceFactory = new(FakeKnSourceFactory) diff --git a/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_run_efactory.go b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_run_efactory.go new file mode 100644 index 0000000000..350f21ba00 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes/fake_run_efactory.go @@ -0,0 +1,505 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package typesfakes + +import ( + "sync" + + "github.com/spf13/cobra" + "k8s.io/client-go/rest" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" +) + +type FakeRunEFactory struct { + CreateRunEStub func() func(cmd *cobra.Command, args []string) error + createRunEMutex sync.RWMutex + createRunEArgsForCall []struct { + } + createRunEReturns struct { + result1 func(cmd *cobra.Command, args []string) error + } + createRunEReturnsOnCall map[int]struct { + result1 func(cmd *cobra.Command, args []string) error + } + DeleteRunEStub func() func(cmd *cobra.Command, args []string) error + deleteRunEMutex sync.RWMutex + deleteRunEArgsForCall []struct { + } + deleteRunEReturns struct { + result1 func(cmd *cobra.Command, args []string) error + } + deleteRunEReturnsOnCall map[int]struct { + result1 func(cmd *cobra.Command, args []string) error + } + DescribeRunEStub func() func(cmd *cobra.Command, args []string) error + describeRunEMutex sync.RWMutex + describeRunEArgsForCall []struct { + } + describeRunEReturns struct { + result1 func(cmd *cobra.Command, args []string) error + } + describeRunEReturnsOnCall map[int]struct { + result1 func(cmd *cobra.Command, args []string) error + } + KnSourceClientStub func(*rest.Config, string) types.KnSourceClient + knSourceClientMutex sync.RWMutex + knSourceClientArgsForCall []struct { + arg1 *rest.Config + arg2 string + } + knSourceClientReturns struct { + result1 types.KnSourceClient + } + knSourceClientReturnsOnCall map[int]struct { + result1 types.KnSourceClient + } + KnSourceFactoryStub func() types.KnSourceFactory + knSourceFactoryMutex sync.RWMutex + knSourceFactoryArgsForCall []struct { + } + knSourceFactoryReturns struct { + result1 types.KnSourceFactory + } + knSourceFactoryReturnsOnCall map[int]struct { + result1 types.KnSourceFactory + } + ListRunEStub func() func(cmd *cobra.Command, args []string) error + listRunEMutex sync.RWMutex + listRunEArgsForCall []struct { + } + listRunEReturns struct { + result1 func(cmd *cobra.Command, args []string) error + } + listRunEReturnsOnCall map[int]struct { + result1 func(cmd *cobra.Command, args []string) error + } + UpdateRunEStub func() func(cmd *cobra.Command, args []string) error + updateRunEMutex sync.RWMutex + updateRunEArgsForCall []struct { + } + updateRunEReturns struct { + result1 func(cmd *cobra.Command, args []string) error + } + updateRunEReturnsOnCall map[int]struct { + result1 func(cmd *cobra.Command, args []string) error + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeRunEFactory) CreateRunE() func(cmd *cobra.Command, args []string) error { + fake.createRunEMutex.Lock() + ret, specificReturn := fake.createRunEReturnsOnCall[len(fake.createRunEArgsForCall)] + fake.createRunEArgsForCall = append(fake.createRunEArgsForCall, struct { + }{}) + stub := fake.CreateRunEStub + fakeReturns := fake.createRunEReturns + fake.recordInvocation("CreateRunE", []interface{}{}) + fake.createRunEMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeRunEFactory) CreateRunECallCount() int { + fake.createRunEMutex.RLock() + defer fake.createRunEMutex.RUnlock() + return len(fake.createRunEArgsForCall) +} + +func (fake *FakeRunEFactory) CreateRunECalls(stub func() func(cmd *cobra.Command, args []string) error) { + fake.createRunEMutex.Lock() + defer fake.createRunEMutex.Unlock() + fake.CreateRunEStub = stub +} + +func (fake *FakeRunEFactory) CreateRunEReturns(result1 func(cmd *cobra.Command, args []string) error) { + fake.createRunEMutex.Lock() + defer fake.createRunEMutex.Unlock() + fake.CreateRunEStub = nil + fake.createRunEReturns = struct { + result1 func(cmd *cobra.Command, args []string) error + }{result1} +} + +func (fake *FakeRunEFactory) CreateRunEReturnsOnCall(i int, result1 func(cmd *cobra.Command, args []string) error) { + fake.createRunEMutex.Lock() + defer fake.createRunEMutex.Unlock() + fake.CreateRunEStub = nil + if fake.createRunEReturnsOnCall == nil { + fake.createRunEReturnsOnCall = make(map[int]struct { + result1 func(cmd *cobra.Command, args []string) error + }) + } + fake.createRunEReturnsOnCall[i] = struct { + result1 func(cmd *cobra.Command, args []string) error + }{result1} +} + +func (fake *FakeRunEFactory) DeleteRunE() func(cmd *cobra.Command, args []string) error { + fake.deleteRunEMutex.Lock() + ret, specificReturn := fake.deleteRunEReturnsOnCall[len(fake.deleteRunEArgsForCall)] + fake.deleteRunEArgsForCall = append(fake.deleteRunEArgsForCall, struct { + }{}) + stub := fake.DeleteRunEStub + fakeReturns := fake.deleteRunEReturns + fake.recordInvocation("DeleteRunE", []interface{}{}) + fake.deleteRunEMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeRunEFactory) DeleteRunECallCount() int { + fake.deleteRunEMutex.RLock() + defer fake.deleteRunEMutex.RUnlock() + return len(fake.deleteRunEArgsForCall) +} + +func (fake *FakeRunEFactory) DeleteRunECalls(stub func() func(cmd *cobra.Command, args []string) error) { + fake.deleteRunEMutex.Lock() + defer fake.deleteRunEMutex.Unlock() + fake.DeleteRunEStub = stub +} + +func (fake *FakeRunEFactory) DeleteRunEReturns(result1 func(cmd *cobra.Command, args []string) error) { + fake.deleteRunEMutex.Lock() + defer fake.deleteRunEMutex.Unlock() + fake.DeleteRunEStub = nil + fake.deleteRunEReturns = struct { + result1 func(cmd *cobra.Command, args []string) error + }{result1} +} + +func (fake *FakeRunEFactory) DeleteRunEReturnsOnCall(i int, result1 func(cmd *cobra.Command, args []string) error) { + fake.deleteRunEMutex.Lock() + defer fake.deleteRunEMutex.Unlock() + fake.DeleteRunEStub = nil + if fake.deleteRunEReturnsOnCall == nil { + fake.deleteRunEReturnsOnCall = make(map[int]struct { + result1 func(cmd *cobra.Command, args []string) error + }) + } + fake.deleteRunEReturnsOnCall[i] = struct { + result1 func(cmd *cobra.Command, args []string) error + }{result1} +} + +func (fake *FakeRunEFactory) DescribeRunE() func(cmd *cobra.Command, args []string) error { + fake.describeRunEMutex.Lock() + ret, specificReturn := fake.describeRunEReturnsOnCall[len(fake.describeRunEArgsForCall)] + fake.describeRunEArgsForCall = append(fake.describeRunEArgsForCall, struct { + }{}) + stub := fake.DescribeRunEStub + fakeReturns := fake.describeRunEReturns + fake.recordInvocation("DescribeRunE", []interface{}{}) + fake.describeRunEMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeRunEFactory) DescribeRunECallCount() int { + fake.describeRunEMutex.RLock() + defer fake.describeRunEMutex.RUnlock() + return len(fake.describeRunEArgsForCall) +} + +func (fake *FakeRunEFactory) DescribeRunECalls(stub func() func(cmd *cobra.Command, args []string) error) { + fake.describeRunEMutex.Lock() + defer fake.describeRunEMutex.Unlock() + fake.DescribeRunEStub = stub +} + +func (fake *FakeRunEFactory) DescribeRunEReturns(result1 func(cmd *cobra.Command, args []string) error) { + fake.describeRunEMutex.Lock() + defer fake.describeRunEMutex.Unlock() + fake.DescribeRunEStub = nil + fake.describeRunEReturns = struct { + result1 func(cmd *cobra.Command, args []string) error + }{result1} +} + +func (fake *FakeRunEFactory) DescribeRunEReturnsOnCall(i int, result1 func(cmd *cobra.Command, args []string) error) { + fake.describeRunEMutex.Lock() + defer fake.describeRunEMutex.Unlock() + fake.DescribeRunEStub = nil + if fake.describeRunEReturnsOnCall == nil { + fake.describeRunEReturnsOnCall = make(map[int]struct { + result1 func(cmd *cobra.Command, args []string) error + }) + } + fake.describeRunEReturnsOnCall[i] = struct { + result1 func(cmd *cobra.Command, args []string) error + }{result1} +} + +func (fake *FakeRunEFactory) KnSourceClient(arg1 *rest.Config, arg2 string) types.KnSourceClient { + fake.knSourceClientMutex.Lock() + ret, specificReturn := fake.knSourceClientReturnsOnCall[len(fake.knSourceClientArgsForCall)] + fake.knSourceClientArgsForCall = append(fake.knSourceClientArgsForCall, struct { + arg1 *rest.Config + arg2 string + }{arg1, arg2}) + stub := fake.KnSourceClientStub + fakeReturns := fake.knSourceClientReturns + fake.recordInvocation("KnSourceClient", []interface{}{arg1, arg2}) + fake.knSourceClientMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeRunEFactory) KnSourceClientCallCount() int { + fake.knSourceClientMutex.RLock() + defer fake.knSourceClientMutex.RUnlock() + return len(fake.knSourceClientArgsForCall) +} + +func (fake *FakeRunEFactory) KnSourceClientCalls(stub func(*rest.Config, string) types.KnSourceClient) { + fake.knSourceClientMutex.Lock() + defer fake.knSourceClientMutex.Unlock() + fake.KnSourceClientStub = stub +} + +func (fake *FakeRunEFactory) KnSourceClientArgsForCall(i int) (*rest.Config, string) { + fake.knSourceClientMutex.RLock() + defer fake.knSourceClientMutex.RUnlock() + argsForCall := fake.knSourceClientArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakeRunEFactory) KnSourceClientReturns(result1 types.KnSourceClient) { + fake.knSourceClientMutex.Lock() + defer fake.knSourceClientMutex.Unlock() + fake.KnSourceClientStub = nil + fake.knSourceClientReturns = struct { + result1 types.KnSourceClient + }{result1} +} + +func (fake *FakeRunEFactory) KnSourceClientReturnsOnCall(i int, result1 types.KnSourceClient) { + fake.knSourceClientMutex.Lock() + defer fake.knSourceClientMutex.Unlock() + fake.KnSourceClientStub = nil + if fake.knSourceClientReturnsOnCall == nil { + fake.knSourceClientReturnsOnCall = make(map[int]struct { + result1 types.KnSourceClient + }) + } + fake.knSourceClientReturnsOnCall[i] = struct { + result1 types.KnSourceClient + }{result1} +} + +func (fake *FakeRunEFactory) KnSourceFactory() types.KnSourceFactory { + fake.knSourceFactoryMutex.Lock() + ret, specificReturn := fake.knSourceFactoryReturnsOnCall[len(fake.knSourceFactoryArgsForCall)] + fake.knSourceFactoryArgsForCall = append(fake.knSourceFactoryArgsForCall, struct { + }{}) + stub := fake.KnSourceFactoryStub + fakeReturns := fake.knSourceFactoryReturns + fake.recordInvocation("KnSourceFactory", []interface{}{}) + fake.knSourceFactoryMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeRunEFactory) KnSourceFactoryCallCount() int { + fake.knSourceFactoryMutex.RLock() + defer fake.knSourceFactoryMutex.RUnlock() + return len(fake.knSourceFactoryArgsForCall) +} + +func (fake *FakeRunEFactory) KnSourceFactoryCalls(stub func() types.KnSourceFactory) { + fake.knSourceFactoryMutex.Lock() + defer fake.knSourceFactoryMutex.Unlock() + fake.KnSourceFactoryStub = stub +} + +func (fake *FakeRunEFactory) KnSourceFactoryReturns(result1 types.KnSourceFactory) { + fake.knSourceFactoryMutex.Lock() + defer fake.knSourceFactoryMutex.Unlock() + fake.KnSourceFactoryStub = nil + fake.knSourceFactoryReturns = struct { + result1 types.KnSourceFactory + }{result1} +} + +func (fake *FakeRunEFactory) KnSourceFactoryReturnsOnCall(i int, result1 types.KnSourceFactory) { + fake.knSourceFactoryMutex.Lock() + defer fake.knSourceFactoryMutex.Unlock() + fake.KnSourceFactoryStub = nil + if fake.knSourceFactoryReturnsOnCall == nil { + fake.knSourceFactoryReturnsOnCall = make(map[int]struct { + result1 types.KnSourceFactory + }) + } + fake.knSourceFactoryReturnsOnCall[i] = struct { + result1 types.KnSourceFactory + }{result1} +} + +func (fake *FakeRunEFactory) ListRunE() func(cmd *cobra.Command, args []string) error { + fake.listRunEMutex.Lock() + ret, specificReturn := fake.listRunEReturnsOnCall[len(fake.listRunEArgsForCall)] + fake.listRunEArgsForCall = append(fake.listRunEArgsForCall, struct { + }{}) + stub := fake.ListRunEStub + fakeReturns := fake.listRunEReturns + fake.recordInvocation("ListRunE", []interface{}{}) + fake.listRunEMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeRunEFactory) ListRunECallCount() int { + fake.listRunEMutex.RLock() + defer fake.listRunEMutex.RUnlock() + return len(fake.listRunEArgsForCall) +} + +func (fake *FakeRunEFactory) ListRunECalls(stub func() func(cmd *cobra.Command, args []string) error) { + fake.listRunEMutex.Lock() + defer fake.listRunEMutex.Unlock() + fake.ListRunEStub = stub +} + +func (fake *FakeRunEFactory) ListRunEReturns(result1 func(cmd *cobra.Command, args []string) error) { + fake.listRunEMutex.Lock() + defer fake.listRunEMutex.Unlock() + fake.ListRunEStub = nil + fake.listRunEReturns = struct { + result1 func(cmd *cobra.Command, args []string) error + }{result1} +} + +func (fake *FakeRunEFactory) ListRunEReturnsOnCall(i int, result1 func(cmd *cobra.Command, args []string) error) { + fake.listRunEMutex.Lock() + defer fake.listRunEMutex.Unlock() + fake.ListRunEStub = nil + if fake.listRunEReturnsOnCall == nil { + fake.listRunEReturnsOnCall = make(map[int]struct { + result1 func(cmd *cobra.Command, args []string) error + }) + } + fake.listRunEReturnsOnCall[i] = struct { + result1 func(cmd *cobra.Command, args []string) error + }{result1} +} + +func (fake *FakeRunEFactory) UpdateRunE() func(cmd *cobra.Command, args []string) error { + fake.updateRunEMutex.Lock() + ret, specificReturn := fake.updateRunEReturnsOnCall[len(fake.updateRunEArgsForCall)] + fake.updateRunEArgsForCall = append(fake.updateRunEArgsForCall, struct { + }{}) + stub := fake.UpdateRunEStub + fakeReturns := fake.updateRunEReturns + fake.recordInvocation("UpdateRunE", []interface{}{}) + fake.updateRunEMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeRunEFactory) UpdateRunECallCount() int { + fake.updateRunEMutex.RLock() + defer fake.updateRunEMutex.RUnlock() + return len(fake.updateRunEArgsForCall) +} + +func (fake *FakeRunEFactory) UpdateRunECalls(stub func() func(cmd *cobra.Command, args []string) error) { + fake.updateRunEMutex.Lock() + defer fake.updateRunEMutex.Unlock() + fake.UpdateRunEStub = stub +} + +func (fake *FakeRunEFactory) UpdateRunEReturns(result1 func(cmd *cobra.Command, args []string) error) { + fake.updateRunEMutex.Lock() + defer fake.updateRunEMutex.Unlock() + fake.UpdateRunEStub = nil + fake.updateRunEReturns = struct { + result1 func(cmd *cobra.Command, args []string) error + }{result1} +} + +func (fake *FakeRunEFactory) UpdateRunEReturnsOnCall(i int, result1 func(cmd *cobra.Command, args []string) error) { + fake.updateRunEMutex.Lock() + defer fake.updateRunEMutex.Unlock() + fake.UpdateRunEStub = nil + if fake.updateRunEReturnsOnCall == nil { + fake.updateRunEReturnsOnCall = make(map[int]struct { + result1 func(cmd *cobra.Command, args []string) error + }) + } + fake.updateRunEReturnsOnCall[i] = struct { + result1 func(cmd *cobra.Command, args []string) error + }{result1} +} + +func (fake *FakeRunEFactory) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.createRunEMutex.RLock() + defer fake.createRunEMutex.RUnlock() + fake.deleteRunEMutex.RLock() + defer fake.deleteRunEMutex.RUnlock() + fake.describeRunEMutex.RLock() + defer fake.describeRunEMutex.RUnlock() + fake.knSourceClientMutex.RLock() + defer fake.knSourceClientMutex.RUnlock() + fake.knSourceFactoryMutex.RLock() + defer fake.knSourceFactoryMutex.RUnlock() + fake.listRunEMutex.RLock() + defer fake.listRunEMutex.RUnlock() + fake.updateRunEMutex.RLock() + defer fake.updateRunEMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeRunEFactory) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ types.RunEFactory = new(FakeRunEFactory) diff --git a/vendor/knative.dev/client-pkg/pkg/kn/commands/describe.go b/vendor/knative.dev/client-pkg/pkg/kn/commands/describe.go new file mode 100644 index 0000000000..89bfdeaf2c --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn/commands/describe.go @@ -0,0 +1,222 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package commands + +import ( + "fmt" + "sort" + "strconv" + "strings" + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/duration" + "knative.dev/client-pkg/pkg/printers" + "knative.dev/pkg/apis" +) + +// Max length When to truncate long strings (when not "all" mode switched on) +const TruncateAt = 100 + +func WriteMetadata(dw printers.PrefixWriter, m *metav1.ObjectMeta, printDetails bool) { + dw.WriteAttribute("Name", m.Name) + dw.WriteAttribute("Namespace", m.Namespace) + WriteMapDesc(dw, m.Labels, "Labels", printDetails) + WriteMapDesc(dw, m.Annotations, "Annotations", printDetails) + dw.WriteAttribute("Age", Age(m.CreationTimestamp.Time)) +} + +var boringDomains = map[string]bool{ + "serving.knative.dev": true, + "client.knative.dev": true, + "kubectl.kubernetes.io": true, +} + +func keyIsBoring(k string) bool { + parts := strings.Split(k, "/") + return len(parts) > 1 && boringDomains[parts[0]] +} + +// Write a map either compact in a single line (possibly truncated) or, if printDetails is set, +// over multiple line, one line per key-value pair. The output is sorted by keys. +func WriteMapDesc(dw printers.PrefixWriter, m map[string]string, label string, details bool) { + if len(m) == 0 { + return + } + + var keys []string + for k := range m { + if details || !keyIsBoring(k) { + keys = append(keys, k) + } + } + if len(keys) == 0 { + return + } + sort.Strings(keys) + + if details { + for i, key := range keys { + l := "" + if i == 0 { + l = printers.Label(label) + } + dw.WriteColsLn(l, key+"="+m[key]) + } + return + } + + dw.WriteColsLn(printers.Label(label), joinAndTruncate(keys, m, TruncateAt-len(label)-2)) +} + +func Age(t time.Time) string { + if t.IsZero() { + return "" + } + return duration.ShortHumanDuration(time.Since(t)) +} + +func formatConditionType(condition apis.Condition) string { + return string(condition.Type) +} + +// Status in ASCII format +func formatStatus(c apis.Condition) string { + switch c.Status { + case corev1.ConditionTrue: + return "++" + case corev1.ConditionFalse: + switch c.Severity { + case apis.ConditionSeverityError: + return "!!" + case apis.ConditionSeverityWarning: + return " W" + case apis.ConditionSeverityInfo: + return " I" + default: + return " !" + } + default: + return "??" + } +} + +// Used for conditions table to do own formatting for the table, +// as the tabbed writer doesn't work nicely with colors +func getMaxTypeLen(conditions []apis.Condition) int { + max := 0 + for _, condition := range conditions { + if len(condition.Type) > max { + max = len(condition.Type) + } + } + return max +} + +// Sort conditions: Ready first, followed by error, then Warning, then Info +func sortConditions(conditions []apis.Condition) []apis.Condition { + // Don't change the orig slice + ret := make([]apis.Condition, len(conditions)) + copy(ret, conditions) + sort.SliceStable(ret, func(i, j int) bool { + ic := &ret[i] + jc := &ret[j] + // Ready first + if ic.Type == apis.ConditionReady { + return jc.Type != apis.ConditionReady + } + if jc.Type == apis.ConditionReady { + return false + } + // Among conditions of the same Severity, sort by Type + if ic.Severity == jc.Severity { + return ic.Type < jc.Type + } + // Error < Warning < Info + switch ic.Severity { + case apis.ConditionSeverityError: + return true + case apis.ConditionSeverityWarning: + return jc.Severity == apis.ConditionSeverityInfo + case apis.ConditionSeverityInfo: + return false + default: + return false + } + }) + return ret +} + +// Print out a table with conditions. +func WriteConditions(dw printers.PrefixWriter, conditions []apis.Condition, printMessage bool) { + section := dw.WriteAttribute("Conditions", "") + conditions = sortConditions(conditions) + maxLen := getMaxTypeLen(conditions) + formatHeader := "%-2s %-" + strconv.Itoa(maxLen) + "s %6s %-s\n" + formatRow := "%-2s %-" + strconv.Itoa(maxLen) + "s %6s %-s\n" + section.Writef(formatHeader, "OK", "TYPE", "AGE", "REASON") + for _, condition := range conditions { + ok := formatStatus(condition) + reason := condition.Reason + if printMessage && reason != "" { + reason = fmt.Sprintf("%s (%s)", reason, condition.Message) + } + section.Writef(formatRow, ok, formatConditionType(condition), Age(condition.LastTransitionTime.Inner.Time), reason) + } +} + +// Writer a slice compact (printDetails == false) in one line, or over multiple line +// with key-value line-by-line (printDetails == true) +func WriteSliceDesc(dw printers.PrefixWriter, s []string, label string, printDetails bool) { + + if len(s) == 0 { + return + } + + if printDetails { + for i, value := range s { + if i == 0 { + dw.WriteColsLn(printers.Label(label), value) + } else { + dw.WriteColsLn("", value) + } + } + return + } + + joined := strings.Join(s, ", ") + if len(joined) > TruncateAt { + joined = joined[:TruncateAt-4] + " ..." + } + dw.WriteAttribute(label, joined) +} + +// Join to key=value pair, comma separated, and truncate if longer than a limit +func joinAndTruncate(sortedKeys []string, m map[string]string, width int) string { + ret := "" + for _, key := range sortedKeys { + ret += fmt.Sprintf("%s=%s, ", key, m[key]) + if len(ret) > width { + break + } + } + // cut of two latest chars + ret = strings.TrimRight(ret, ", ") + if len(ret) <= width { + return ret + } + return ret[:width-4] + " ..." +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn/commands/flags/listprint.go b/vendor/knative.dev/client-pkg/pkg/kn/commands/flags/listprint.go new file mode 100644 index 0000000000..ed562c9e19 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn/commands/flags/listprint.go @@ -0,0 +1,102 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package flags + +import ( + "io" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/cli-runtime/pkg/genericclioptions" + + "knative.dev/client-pkg/pkg/kn/commands" + hprinters "knative.dev/client-pkg/pkg/printers" + "knative.dev/client-pkg/pkg/util" +) + +// ListFlags composes common printer flag structs +// used in the list command. +type ListPrintFlags struct { + GenericPrintFlags *genericclioptions.PrintFlags + HumanReadableFlags *commands.HumanPrintFlags + PrinterHandler func(h hprinters.PrintHandler) +} + +// AllowedFormats is the list of formats in which data can be displayed +func (f *ListPrintFlags) AllowedFormats() []string { + formats := f.GenericPrintFlags.AllowedFormats() + formats = append(formats, f.HumanReadableFlags.AllowedFormats()...) + return formats +} + +// ToPrinter attempts to find a composed set of ListTypesFlags suitable for +// returning a printer based on current flag values. +func (f *ListPrintFlags) ToPrinter() (hprinters.ResourcePrinter, error) { + // if there are flags specified for generic printing + if f.GenericPrintFlags.OutputFlagSpecified() { + p, err := f.GenericPrintFlags.ToPrinter() + if err != nil { + return nil, err + } + return p, nil + } + + p, err := f.HumanReadableFlags.ToPrinter(f.PrinterHandler) + if err != nil { + return nil, err + } + return p, nil +} + +// Print is to print an Object to a Writer +func (f *ListPrintFlags) Print(obj runtime.Object, w io.Writer) error { + printer, err := f.ToPrinter() + if err != nil { + return err + } + + if f.GenericPrintFlags.OutputFlagSpecified() { + unstructuredList, err := util.ToUnstructuredList(obj) + if err != nil { + return err + } + return printer.PrintObj(unstructuredList, w) + } + + return printer.PrintObj(obj, w) +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to humanreadable and template printing. +func (f *ListPrintFlags) AddFlags(cmd *cobra.Command) { + f.GenericPrintFlags.AddFlags(cmd) + f.HumanReadableFlags.AddFlags(cmd) +} + +// NewListFlags returns flags associated with humanreadable, +// template, and "name" printing, with default values set. +func NewListPrintFlags(printer func(h hprinters.PrintHandler)) *ListPrintFlags { + return &ListPrintFlags{ + GenericPrintFlags: genericclioptions.NewPrintFlags(""), + HumanReadableFlags: commands.NewHumanPrintFlags(), + PrinterHandler: printer, + } +} + +// EnsureWithNamespace ensures that humanreadable flags return +// a printer capable of printing with a "namespace" column. +func (f *ListPrintFlags) EnsureWithNamespace() { + f.HumanReadableFlags.EnsureWithNamespace() +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn/commands/flags/sink.go b/vendor/knative.dev/client-pkg/pkg/kn/commands/flags/sink.go new file mode 100644 index 0000000000..509b82450b --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn/commands/flags/sink.go @@ -0,0 +1,179 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package flags + +import ( + "context" + "fmt" + "strings" + + "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" + + clientdynamic "knative.dev/client-pkg/pkg/dynamic" + "knative.dev/client-pkg/pkg/kn/config" +) + +type SinkFlags struct { + sink string +} + +// AddWithFlagName configures sink flag with given flag name and a short flag name +// pass empty short flag name if you dont want to set one +func (i *SinkFlags) AddWithFlagName(cmd *cobra.Command, fname, short string) { + flag := "--" + fname + if short == "" { + cmd.Flags().StringVar(&i.sink, fname, "", "") + } else { + cmd.Flags().StringVarP(&i.sink, fname, short, "", "") + } + cmd.Flag(fname).Usage = "Addressable sink for events. " + + "You can specify a broker, channel, Knative service or URI. " + + "Examples: '" + flag + " broker:nest' for a broker 'nest', " + + "'" + flag + " channel:pipe' for a channel 'pipe', " + + "'" + flag + " ksvc:mysvc:mynamespace' for a Knative service 'mysvc' in another namespace 'mynamespace', " + + "'" + flag + " https://event.receiver.uri' for an URI with an 'http://' or 'https://' schema, " + + "'" + flag + " ksvc:receiver' or simply '" + flag + " receiver' for a Knative service 'receiver' in the current namespace. " + + "If a prefix is not provided, it is considered as a Knative service in the current namespace. " + + "If referring to a Knative service in another namespace, 'ksvc:name:namespace' combination must be provided explicitly." + + for _, p := range config.GlobalConfig.SinkMappings() { + //user configuration might override the default configuration + sinkMappings[p.Prefix] = schema.GroupVersionResource{ + Resource: p.Resource, + Group: p.Group, + Version: p.Version, + } + } +} + +// Add configures sink flag with name 'sink' amd short name 's' +func (i *SinkFlags) Add(cmd *cobra.Command) { + i.AddWithFlagName(cmd, "sink", "s") +} + +// sinkPrefixes maps prefixes used for sinks to their GroupVersionResources. +var sinkMappings = map[string]schema.GroupVersionResource{ + "broker": { + Resource: "brokers", + Group: "eventing.knative.dev", + Version: "v1", + }, + // Shorthand alias for service + "ksvc": { + Resource: "services", + Group: "serving.knative.dev", + Version: "v1", + }, + "channel": { + Resource: "channels", + Group: "messaging.knative.dev", + Version: "v1", + }, +} + +// ResolveSink returns the Destination referred to by the flags in the acceptor. +// It validates that any object the user is referring to exists. +func (i *SinkFlags) ResolveSink(ctx context.Context, knclient clientdynamic.KnDynamicClient, namespace string) (*duckv1.Destination, error) { + client := knclient.RawClient() + if i.sink == "" { + return nil, nil + } + prefix, name, ns := parseSink(i.sink) + if prefix == "" { + // URI target + uri, err := apis.ParseURL(name) + if err != nil { + return nil, err + } + return &duckv1.Destination{URI: uri}, nil + } + typ, ok := sinkMappings[prefix] + if !ok { + if prefix == "svc" || prefix == "service" { + return nil, fmt.Errorf("unsupported sink prefix: '%s', please use prefix 'ksvc' for knative service", prefix) + } + idx := strings.LastIndex(prefix, "/") + var groupVersion string + var kind string + if idx != -1 && idx < len(prefix)-1 { + groupVersion, kind = prefix[:idx], prefix[idx+1:] + } else { + kind = prefix + } + parsedVersion, _ := schema.ParseGroupVersion(groupVersion) + + if !strings.HasSuffix(kind, "s") { + kind = kind + "s" + } + typ = schema.GroupVersionResource{ + Group: parsedVersion.Group, + Version: parsedVersion.Version, + Resource: kind, + } + } + if ns != "" { + namespace = ns + } + obj, err := client.Resource(typ).Namespace(namespace).Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return nil, err + } + + destination := &duckv1.Destination{ + Ref: &duckv1.KReference{ + Kind: obj.GetKind(), + APIVersion: obj.GetAPIVersion(), + Name: obj.GetName(), + Namespace: namespace, + }, + } + return destination, nil +} + +// parseSink takes the string given by the user into the prefix, name and namespace of +// the object. If the user put a URI instead, the prefix is empty and the name +// is the whole URI. +func parseSink(sink string) (string, string, string) { + parts := strings.SplitN(sink, ":", 3) + switch { + case len(parts) == 1: + return "ksvc", parts[0], "" + case parts[0] == "http" || parts[0] == "https": + return "", sink, "" + case len(parts) == 3: + return parts[0], parts[1], parts[2] + default: + return parts[0], parts[1], "" + } +} + +// SinkToString prepares a sink for list output +func SinkToString(sink duckv1.Destination) string { + if sink.Ref != nil { + if sink.Ref.Kind == "Service" && strings.HasPrefix(sink.Ref.APIVersion, sinkMappings["ksvc"].Group) { + return fmt.Sprintf("ksvc:%s", sink.Ref.Name) + } else { + return fmt.Sprintf("%s:%s", strings.ToLower(sink.Ref.Kind), sink.Ref.Name) + } + } + if sink.URI != nil { + return sink.URI.String() + } + return "" +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn/commands/human_readable_flags.go b/vendor/knative.dev/client-pkg/pkg/kn/commands/human_readable_flags.go new file mode 100644 index 0000000000..faa477e2d6 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn/commands/human_readable_flags.go @@ -0,0 +1,121 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package commands + +import ( + "fmt" + "time" + + "github.com/spf13/cobra" + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/duration" + hprinters "knative.dev/client-pkg/pkg/printers" + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +// HumanPrintFlags provides default flags necessary for printing. +// Given the following flag values, a printer can be requested that knows +// how to handle printing based on these values. +type HumanPrintFlags struct { + WithNamespace bool + NoHeaders bool + //TODO: Add more flags as required +} + +// AllowedFormats returns more customized formating options +func (f *HumanPrintFlags) AllowedFormats() []string { + // TODO: Add more formats eg: wide + return []string{"no-headers"} +} + +// ToPrinter receives returns a printer capable of +// handling human-readable output. +func (f *HumanPrintFlags) ToPrinter(getHandlerFunc func(h hprinters.PrintHandler)) (hprinters.ResourcePrinter, error) { + p := hprinters.NewTablePrinter(hprinters.PrintOptions{AllNamespaces: f.WithNamespace, NoHeaders: f.NoHeaders}) + getHandlerFunc(p) + return p, nil +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to human-readable printing to it +func (f *HumanPrintFlags) AddFlags(c *cobra.Command) { + c.Flags().BoolVar(&f.NoHeaders, "no-headers", false, "When using the default output format, don't print headers (default: print headers).") + //TODO: Add more flags as required +} + +// NewHumanPrintFlags returns flags associated with +// human-readable printing, with default values set. +func NewHumanPrintFlags() *HumanPrintFlags { + return &HumanPrintFlags{} +} + +// EnsureWithNamespace sets the "WithNamespace" humanreadable option to true. +func (f *HumanPrintFlags) EnsureWithNamespace() { + f.WithNamespace = true +} + +// conditionsValue returns the True conditions count among total conditions +func ConditionsValue(conditions duckv1.Conditions) string { + var ok int + for _, condition := range conditions { + if condition.Status == "True" { + ok++ + } + } + return fmt.Sprintf("%d OK / %d", ok, len(conditions)) +} + +// readyCondition returns status of resource's Ready type condition +func ReadyCondition(conditions duckv1.Conditions) string { + for _, condition := range conditions { + if condition.Type == apis.ConditionReady { + return string(condition.Status) + } + } + return "" +} + +// NonReadyConditionReason returns formatted string of +// reason and message for non ready conditions +func NonReadyConditionReason(conditions duckv1.Conditions) string { + for _, condition := range conditions { + if condition.Type == apis.ConditionReady { + if string(condition.Status) == "True" { + return "" + } + if condition.Message != "" { + return fmt.Sprintf("%s : %s", condition.Reason, condition.Message) + } + return condition.Reason + } + } + return "" +} + +// translateTimestampSince returns the elapsed time since timestamp in +// human-readable approximation. +func TranslateTimestampSince(timestamp metav1.Time) string { + if timestamp.IsZero() { + return "" + } + return duration.HumanDuration(time.Since(timestamp.Time)) +} + +// AddGitOpsFlags adds flags to enable gitops mode +func AddGitOpsFlags(flags *pflag.FlagSet) { + flags.String("target", "", "Work on local directory instead of a remote cluster (experimental)") +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn/commands/namespaced.go b/vendor/knative.dev/client-pkg/pkg/kn/commands/namespaced.go new file mode 100644 index 0000000000..3b7b90128a --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn/commands/namespaced.go @@ -0,0 +1,92 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package commands + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "k8s.io/client-go/tools/clientcmd" +) + +// AddNamespaceFlags adds the namespace-related flags: +// * --namespace +// * --all-namespaces +func AddNamespaceFlags(flags *pflag.FlagSet, allowAll bool) { + flags.StringP( + "namespace", + "n", + "", + "Specify the namespace to operate in.", + ) + + if allowAll { + flags.BoolP( + "all-namespaces", + "A", + false, + "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.", + ) + } +} + +// GetNamespace returns namespace from command specified by flag +func (params *KnParams) GetNamespace(cmd *cobra.Command) (string, error) { + namespaceFlag := cmd.Flag("namespace") + if namespaceFlag == nil { + return "", fmt.Errorf("command %s doesn't have --namespace flag", cmd.Name()) + } + namespace := namespaceFlag.Value.String() + // check value of all-namespaces only if its defined + if cmd.Flags().Lookup("all-namespaces") != nil { + all, err := cmd.Flags().GetBool("all-namespaces") + if err != nil { + return "", err + } else if all { // if all-namespaces=True + // namespace = "" <-- all-namespaces representation + return "", nil + } + } + // if all-namespaces=False or namespace not given, use default namespace + if namespace == "" { + var err error + namespace, err = params.CurrentNamespace() + if err != nil { + if !clientcmd.IsEmptyConfig(err) { + return "", err + } + // If no current namespace is set use "default" + namespace = "default" + } + } + return namespace, nil +} + +// CurrentNamespace returns the current namespace which is either provided as option or picked up from kubeconfig +func (params *KnParams) CurrentNamespace() (string, error) { + var err error + if params.fixedCurrentNamespace != "" { + return params.fixedCurrentNamespace, nil + } + if params.ClientConfig == nil { + params.ClientConfig, err = params.GetClientConfig() + if err != nil { + return "", err + } + } + name, _, err := params.ClientConfig.Namespace() + return name, err +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn/commands/testing_helper.go b/vendor/knative.dev/client-pkg/pkg/kn/commands/testing_helper.go new file mode 100644 index 0000000000..2f23da9b54 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn/commands/testing_helper.go @@ -0,0 +1,98 @@ +// Copyright © 2018 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 commands + +import ( + "bytes" + + "knative.dev/client-pkg/pkg/dynamic/fake" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime" + clienttesting "k8s.io/client-go/testing" + servingv1fake "knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1/fake" + + "knative.dev/client-pkg/pkg/kn/flags" + clientservingv1 "knative.dev/client-pkg/pkg/serving/v1" + v1 "knative.dev/client-pkg/pkg/sources/v1" + + sourcesv1fake "knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1/fake" + + clientdynamic "knative.dev/client-pkg/pkg/dynamic" +) + +const FakeNamespace = "current" + +// CreateTestKnCommand helper for creating test commands +func CreateTestKnCommand(cmd *cobra.Command, knParams *KnParams) (*cobra.Command, *servingv1fake.FakeServingV1, *bytes.Buffer) { + buf := new(bytes.Buffer) + fakeServing := &servingv1fake.FakeServingV1{Fake: &clienttesting.Fake{}} + knParams.Output = buf + knParams.NewServingClient = func(namespace string) (clientservingv1.KnServingClient, error) { + return clientservingv1.NewKnServingClient(fakeServing, FakeNamespace), nil + } + knParams.fixedCurrentNamespace = FakeNamespace + knCommand := NewTestCommand(cmd, knParams) + return knCommand, fakeServing, buf +} + +// CreateSourcesTestKnCommand helper for creating test commands +func CreateSourcesTestKnCommand(cmd *cobra.Command, knParams *KnParams) (*cobra.Command, *sourcesv1fake.FakeSourcesV1, *bytes.Buffer) { + buf := new(bytes.Buffer) + // create fake serving client because the sink of source depends on serving client + fakeServing := &servingv1fake.FakeServingV1{Fake: &clienttesting.Fake{}} + knParams.NewServingClient = func(namespace string) (clientservingv1.KnServingClient, error) { + return clientservingv1.NewKnServingClient(fakeServing, FakeNamespace), nil + } + // create fake sources client + fakeEventing := &sourcesv1fake.FakeSourcesV1{Fake: &clienttesting.Fake{}} + knParams.Output = buf + knParams.NewSourcesClient = func(namespace string) (v1.KnSourcesClient, error) { + return v1.NewKnSourcesClient(fakeEventing, FakeNamespace), nil + } + knParams.fixedCurrentNamespace = FakeNamespace + knCommand := NewTestCommand(cmd, knParams) + return knCommand, fakeEventing, buf +} + +// CreateDynamicTestKnCommand helper for creating test commands using dynamic client +func CreateDynamicTestKnCommand(cmd *cobra.Command, knParams *KnParams, objects ...runtime.Object) (*cobra.Command, *clientdynamic.KnDynamicClient, *bytes.Buffer) { + buf := new(bytes.Buffer) + fakeDynamic := fake.CreateFakeKnDynamicClient(FakeNamespace, objects...) + knParams.Output = buf + knParams.NewDynamicClient = func(namespace string) (clientdynamic.KnDynamicClient, error) { + return fakeDynamic, nil + } + + knParams.fixedCurrentNamespace = FakeNamespace + knCommand := NewTestCommand(cmd, knParams) + return knCommand, &fakeDynamic, buf + +} + +// NewTestCommand can be used by tes +func NewTestCommand(subCommand *cobra.Command, params *KnParams) *cobra.Command { + rootCmd := &cobra.Command{ + Use: "kn", + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + return flags.ReconcileBoolFlags(cmd.Flags()) + }, + } + if params.Output != nil { + rootCmd.SetOut(params.Output) + } + rootCmd.AddCommand(subCommand) + return rootCmd +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn/commands/types.go b/vendor/knative.dev/client-pkg/pkg/kn/commands/types.go new file mode 100644 index 0000000000..bc78f4c302 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn/commands/types.go @@ -0,0 +1,268 @@ +// Copyright © 2018 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 commands + +import ( + "fmt" + "io" + "os" + "path/filepath" + + "k8s.io/client-go/dynamic" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + eventingv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1" + eventingv1beta1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1beta1" + messagingv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/messaging/v1" + sourcesv1client "knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1" + sourcesv1beta2client "knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1beta2" + servingv1client "knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1" + servingv1alpha1client "knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1alpha1" + + "knative.dev/client-pkg/pkg/util" + + clientdynamic "knative.dev/client-pkg/pkg/dynamic" + knerrors "knative.dev/client-pkg/pkg/errors" + clienteventingv1 "knative.dev/client-pkg/pkg/eventing/v1" + clienteventingv1beta1 "knative.dev/client-pkg/pkg/eventing/v1beta1" + clientmessagingv1 "knative.dev/client-pkg/pkg/messaging/v1" + clientservingv1 "knative.dev/client-pkg/pkg/serving/v1" + clientservingv1alpha1 "knative.dev/client-pkg/pkg/serving/v1alpha1" + clientsourcesv1 "knative.dev/client-pkg/pkg/sources/v1" + clientsourcesv1beta2 "knative.dev/client-pkg/pkg/sources/v1beta2" +) + +// KnParams for creating commands. Useful for inserting mocks for testing. +type KnParams struct { + Output io.Writer + KubeCfgPath string + KubeContext string + KubeCluster string + KubeAsUser string + KubeAsUID string + KubeAsGroup []string + ClientConfig clientcmd.ClientConfig + NewServingClient func(namespace string) (clientservingv1.KnServingClient, error) + NewServingV1alpha1Client func(namespace string) (clientservingv1alpha1.KnServingClient, error) + NewGitopsServingClient func(namespace string, dir string) (clientservingv1.KnServingClient, error) + NewSourcesClient func(namespace string) (clientsourcesv1.KnSourcesClient, error) + NewSourcesV1beta2Client func(namespace string) (clientsourcesv1beta2.KnSourcesClient, error) + NewEventingClient func(namespace string) (clienteventingv1.KnEventingClient, error) + NewMessagingClient func(namespace string) (clientmessagingv1.KnMessagingClient, error) + NewDynamicClient func(namespace string) (clientdynamic.KnDynamicClient, error) + NewEventingV1beta1Client func(namespace string) (clienteventingv1beta1.KnEventingV1Beta1Client, error) + + // General global options + LogHTTP bool + + // Set this if you want to nail down the namespace + fixedCurrentNamespace string +} + +func (params *KnParams) Initialize() { + if params.NewServingClient == nil { + params.NewServingClient = params.newServingClient + } + + if params.NewServingV1alpha1Client == nil { + params.NewServingV1alpha1Client = params.newServingClientV1alpha1 + } + + if params.NewGitopsServingClient == nil { + params.NewGitopsServingClient = params.newGitopsServingClient + } + + if params.NewSourcesClient == nil { + params.NewSourcesClient = params.newSourcesClient + } + + if params.NewEventingClient == nil { + params.NewEventingClient = params.newEventingClient + } + + if params.NewMessagingClient == nil { + params.NewMessagingClient = params.newMessagingClient + } + + if params.NewDynamicClient == nil { + params.NewDynamicClient = params.newDynamicClient + } + + if params.NewSourcesV1beta2Client == nil { + params.NewSourcesV1beta2Client = params.newSourcesClientV1beta2 + } + + if params.NewEventingV1beta1Client == nil { + params.NewEventingV1beta1Client = params.newEventingV1Beta1Client + } +} + +func (params *KnParams) newServingClient(namespace string) (clientservingv1.KnServingClient, error) { + restConfig, err := params.RestConfig() + if err != nil { + return nil, err + } + + client, err := servingv1client.NewForConfig(restConfig) + if err != nil { + return nil, err + } + return clientservingv1.NewKnServingClient(client, namespace), nil +} + +func (params *KnParams) newServingClientV1alpha1(namespace string) (clientservingv1alpha1.KnServingClient, error) { + restConfig, err := params.RestConfig() + if err != nil { + return nil, err + } + + client, err := servingv1alpha1client.NewForConfig(restConfig) + if err != nil { + return nil, err + } + return clientservingv1alpha1.NewKnServingClient(client, namespace), nil +} + +func (params *KnParams) newGitopsServingClient(namespace string, dir string) (clientservingv1.KnServingClient, error) { + return clientservingv1.NewKnServingGitOpsClient(namespace, dir), nil +} + +func (params *KnParams) newSourcesClient(namespace string) (clientsourcesv1.KnSourcesClient, error) { + restConfig, err := params.RestConfig() + if err != nil { + return nil, err + } + + client, _ := sourcesv1client.NewForConfig(restConfig) + return clientsourcesv1.NewKnSourcesClient(client, namespace), nil +} + +func (params *KnParams) newSourcesClientV1beta2(namespace string) (clientsourcesv1beta2.KnSourcesClient, error) { + restConfig, err := params.RestConfig() + if err != nil { + return nil, err + } + + client, _ := sourcesv1beta2client.NewForConfig(restConfig) + return clientsourcesv1beta2.NewKnSourcesClient(client, namespace), nil +} + +func (params *KnParams) newEventingClient(namespace string) (clienteventingv1.KnEventingClient, error) { + restConfig, err := params.RestConfig() + if err != nil { + return nil, err + } + + client, _ := eventingv1.NewForConfig(restConfig) + return clienteventingv1.NewKnEventingClient(client, namespace), nil +} + +func (params *KnParams) newEventingV1Beta1Client(namespace string) (clienteventingv1beta1.KnEventingV1Beta1Client, error) { + restConfig, err := params.RestConfig() + if err != nil { + return nil, err + } + + client, _ := eventingv1beta1.NewForConfig(restConfig) + return clienteventingv1beta1.NewKnEventingV1Beta1Client(client, namespace), nil +} + +func (params *KnParams) newMessagingClient(namespace string) (clientmessagingv1.KnMessagingClient, error) { + restConfig, err := params.RestConfig() + if err != nil { + return nil, err + } + + client, _ := messagingv1.NewForConfig(restConfig) + return clientmessagingv1.NewKnMessagingClient(client, namespace), nil +} + +func (params *KnParams) newDynamicClient(namespace string) (clientdynamic.KnDynamicClient, error) { + restConfig, err := params.RestConfig() + if err != nil { + return nil, err + } + + client, _ := dynamic.NewForConfig(restConfig) + return clientdynamic.NewKnDynamicClient(client, namespace), nil +} + +// RestConfig returns REST config, which can be to use to create specific clientset +func (params *KnParams) RestConfig() (*rest.Config, error) { + var err error + + if params.ClientConfig == nil { + params.ClientConfig, err = params.GetClientConfig() + if err != nil { + return nil, knerrors.GetError(err) + } + } + + config, err := params.ClientConfig.ClientConfig() + if err != nil { + return nil, knerrors.GetError(err) + } + if params.LogHTTP { + config.Wrap(util.NewLoggingTransport) + } + // Override client-go's warning handler to give us nicely printed warnings. + config.WarningHandler = rest.NewWarningWriter(os.Stderr, rest.WarningWriterOptions{ + // only print a given warning the first time we receive it + Deduplicate: true, + }) + + return config, nil +} + +// GetClientConfig gets ClientConfig from KubeCfgPath +func (params *KnParams) GetClientConfig() (clientcmd.ClientConfig, error) { + loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() + configOverrides := &clientcmd.ConfigOverrides{} + if params.KubeContext != "" { + configOverrides.CurrentContext = params.KubeContext + } + if params.KubeCluster != "" { + configOverrides.Context.Cluster = params.KubeCluster + } + if params.KubeAsUser != "" { + configOverrides.AuthInfo.Impersonate = params.KubeAsUser + } + if params.KubeAsUID != "" { + configOverrides.AuthInfo.ImpersonateUID = params.KubeAsUID + } + if len(params.KubeAsGroup) > 0 { + configOverrides.AuthInfo.ImpersonateGroups = params.KubeAsGroup + } + if len(params.KubeCfgPath) == 0 { + return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides), nil + } + + _, err := os.Stat(params.KubeCfgPath) + if err == nil { + loadingRules.ExplicitPath = params.KubeCfgPath + return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides), nil + } + + if !os.IsNotExist(err) { + return nil, err + } + + paths := filepath.SplitList(params.KubeCfgPath) + if len(paths) > 1 { + return nil, fmt.Errorf("can not find config file. '%s' looks like a path. "+ + "Please use the env var KUBECONFIG if you want to check for multiple configuration files", params.KubeCfgPath) + } + return nil, fmt.Errorf("config file '%s' can not be found", params.KubeCfgPath) +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn/config/config.go b/vendor/knative.dev/client-pkg/pkg/kn/config/config.go new file mode 100644 index 0000000000..e1b6340ce8 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn/config/config.go @@ -0,0 +1,283 @@ +// 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 config + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "runtime" + + homedir "github.com/mitchellh/go-homedir" + flag "github.com/spf13/pflag" + "github.com/spf13/viper" +) + +// bootstrapDefaults are the defaults values to use +type defaultConfig struct { + configFile string + pluginsDir string + lookupPluginsInPath bool +} + +// Initialize defaults +var bootstrapDefaults = initDefaults() + +const configContentDefaults = `# Taken from https://github.com/knative/client/blob/main/docs/README.md#options +# +#plugins: +# directory: ~/.config/kn/plugins +#eventing: +# sink-mappings: +# - prefix: svc +# group: core +# version: v1 +# resource: services +# channel-type-mappings: +# - alias: Kafka +# group: messaging.knative.dev +# version: v1alpha1 +# kind: KafkaChannel +` + +// config contains the variables for the Kn config +type config struct { + // configFile is the config file location + configFile string + + // sinkMappings is a list of sink mapping + sinkMappings []SinkMapping + + // channelTypeMappings is a list of channel type mapping + channelTypeMappings []ChannelTypeMapping +} + +// ConfigFile returns the config file which is either the default XDG conform +// config file location or the one set with --config +func (c *config) ConfigFile() string { + if c.configFile != "" { + return c.configFile + } + return bootstrapDefaults.configFile +} + +// PluginsDir returns the plugins' directory +func (c *config) PluginsDir() string { + if viper.IsSet(keyPluginsDirectory) { + return viper.GetString(keyPluginsDirectory) + } else if viper.IsSet(legacyKeyPluginsDirectory) { + // Remove that branch if legacy option is switched off + return viper.GetString(legacyKeyPluginsDirectory) + } else { + return bootstrapDefaults.pluginsDir + } +} + +// LookupPluginsInPath returns true if plugins should be also checked in the pat +func (c *config) LookupPluginsInPath() bool { + return bootstrapDefaults.lookupPluginsInPath +} + +func (c *config) SinkMappings() []SinkMapping { + return c.sinkMappings +} + +func (c *config) ChannelTypeMappings() []ChannelTypeMapping { + return c.channelTypeMappings +} + +// Config used for flag binding +var globalConfig = config{} + +// GlobalConfig is the global configuration available for every sub-command +var GlobalConfig Config = &globalConfig + +// BootstrapConfig reads in config file and bootstrap options if set. +func BootstrapConfig() error { + + // Create a new FlagSet for the bootstrap flags and parse those. This will + // initialize the config file to use (obtained via GlobalConfig.ConfigFile()) + bootstrapFlagSet := flag.NewFlagSet("kn", flag.ContinueOnError) + AddBootstrapFlags(bootstrapFlagSet) + bootstrapFlagSet.ParseErrorsWhitelist = flag.ParseErrorsWhitelist{UnknownFlags: true} // wokeignore:rule=whitelist // TODO(#1031) + bootstrapFlagSet.Usage = func() {} + err := bootstrapFlagSet.Parse(os.Args) + if err != nil && !errors.Is(err, flag.ErrHelp) { + return err + } + + // Bind flags so that options that have been provided have priority. + // Important: Always read options via GlobalConfig methods + err = viper.BindPFlag(keyPluginsDirectory, bootstrapFlagSet.Lookup(flagPluginsDir)) + if err != nil { + return err + } + + viper.SetConfigFile(GlobalConfig.ConfigFile()) + configFile := GlobalConfig.ConfigFile() + _, err = os.Lstat(configFile) + if err != nil { + if !os.IsNotExist(err) { + return fmt.Errorf("cannot stat configfile %s: %w", configFile, err) + } + if err := os.MkdirAll(filepath.Dir(viper.ConfigFileUsed()), 0775); err != nil { + // Can't create config directory, proceed silently without reading the config + return nil + } + if err := os.WriteFile(viper.ConfigFileUsed(), []byte(configContentDefaults), 0600); err != nil { + // Can't create config file, proceed silently without reading the config + return nil + } + } + + viper.AutomaticEnv() // read in environment variables that match + + // Defaults are taken from the parsed flags, which in turn have bootstrap defaults + // TODO: Re-enable when legacy handling for plugin config has been removed + // For now default handling is happening directly in the getter of GlobalConfig + // viper.SetDefault(keyPluginsDirectory, bootstrapDefaults.pluginsDir) + + // If a config file is found, read it in. + err = viper.ReadInConfig() + if err != nil { + return err + } + + // Deserialize sink mappings if configured + err = parseSinkMappings() + if err != nil { + return err + } + + // Deserialize channel type mappings if configured + err = parseChannelTypeMappings() + return err +} + +// Add bootstrap flags use in a separate bootstrap proceeds +func AddBootstrapFlags(flags *flag.FlagSet) { + flags.StringVar(&globalConfig.configFile, "config", "", fmt.Sprintf("kn configuration file (default: %s)", defaultConfigFileForUsageMessage())) + flags.String(flagPluginsDir, "", "Directory holding kn plugins") + + // Let's try that and mark the flags as hidden: (as those configuration is a permanent choice of operation) + flags.MarkHidden(flagPluginsDir) +} + +// =========================================================================================================== + +// Initialize defaults. This happens lazily go allow to change the +// home directory for e.g. tests +func initDefaults() *defaultConfig { + return &defaultConfig{ + configFile: defaultConfigLocation("config.yaml"), + pluginsDir: defaultConfigLocation("plugins"), + lookupPluginsInPath: true, + } +} + +func defaultConfigLocation(subpath string) string { + var base string + if runtime.GOOS == "windows" { + base = defaultConfigDirWindows() + } else { + base = defaultConfigDirUnix() + } + return filepath.Join(base, subpath) +} + +func defaultConfigDirUnix() string { + home, err := homedir.Dir() + if err != nil { + home = "~" + } + + // Check the deprecated path first and fallback to it, add warning to error message + if configHome := filepath.Join(home, ".kn"); dirExists(configHome) { + migrationPath := filepath.Join(home, ".config", "kn") + fmt.Fprintf(os.Stderr, "WARNING: deprecated kn config directory '%s' detected. Please move your configuration to '%s'\n", configHome, migrationPath) + return configHome + } + + // Respect XDG_CONFIG_HOME if set + if xdgHome := os.Getenv("XDG_CONFIG_HOME"); xdgHome != "" { + return filepath.Join(xdgHome, "kn") + } + // Fallback to XDG default for both Linux and macOS + // ~/.config/kn + return filepath.Join(home, ".config", "kn") +} + +func defaultConfigDirWindows() string { + home, err := homedir.Dir() + if err != nil { + // Check the deprecated path first and fallback to it, add warning to error message + if configHome := filepath.Join(home, ".kn"); dirExists(configHome) { + migrationPath := filepath.Join(os.Getenv("APPDATA"), "kn") + fmt.Fprintf(os.Stderr, "WARNING: deprecated kn config directory '%s' detected. Please move your configuration to '%s'\n", configHome, migrationPath) + return configHome + } + } + + return filepath.Join(os.Getenv("APPDATA"), "kn") +} + +func dirExists(path string) bool { + if _, err := os.Stat(path); !os.IsNotExist(err) { + return true + } + return false +} + +// parse sink mappings and store them in the global configuration +func parseSinkMappings() error { + // Parse sink configuration + key := "" + if viper.IsSet(keySinkMappings) { + key = keySinkMappings + } + if key == "" && viper.IsSet(legacyKeySinkMappings) { + key = legacyKeySinkMappings + } + + if key != "" { + err := viper.UnmarshalKey(key, &globalConfig.sinkMappings) + if err != nil { + return fmt.Errorf("error while parsing sink mappings in configuration file %s: %w", + viper.ConfigFileUsed(), err) + } + } + return nil +} + +// parse channel type mappings and store them in the global configuration +func parseChannelTypeMappings() error { + if viper.IsSet(keyChannelTypeMappings) { + err := viper.UnmarshalKey(keyChannelTypeMappings, &globalConfig.channelTypeMappings) + if err != nil { + return fmt.Errorf("error while parsing channel type mappings in configuration file %s: %w", + viper.ConfigFileUsed(), err) + } + } + return nil +} + +// Prepare the default config file for the usage message +func defaultConfigFileForUsageMessage() string { + if runtime.GOOS == "windows" { + return "%APPDATA%\\kn\\config.yaml" + } + return "~/.config/kn/config.yaml" +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn/config/types.go b/vendor/knative.dev/client-pkg/pkg/kn/config/types.go new file mode 100644 index 0000000000..2ef7dc8de7 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn/config/types.go @@ -0,0 +1,88 @@ +// 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 config + +// Package for holding configuration types used in bootstrapping +// and for types in configuration files + +type Config interface { + + // ConfigFile returns the location of the configuration file + ConfigFile() string + + // PluginsDir returns the path to the directory containing plugins + PluginsDir() string + + // LookupPluginsInPath returns true if plugins should be also looked up + // in the execution path + LookupPluginsInPath() bool + + // SinkMappings returns additional mappings for sink prefixes to resources + SinkMappings() []SinkMapping + + // ChannelTypeMappings returns additional mappings for channel type aliases + ChannelTypeMappings() []ChannelTypeMapping +} + +// SinkMappings is the struct of sink prefix config in kn config +type SinkMapping struct { + + // Prefix is the mapping prefix (like "svc") + Prefix string + + // Resource is the name for the mapped resource (like "services", mind the plural) + Resource string + + // Group is the api group for the mapped resource (like "core") + Group string + + // Version is the api version for the mapped resource (like "v1") + Version string +} + +// ChannelTypeMapping is the struct of ChannelType alias config in kn config +type ChannelTypeMapping struct { + + // Alias is the mapping alias (like "kafka") + Alias string + + // Kind is the name for the mapped resource kind (like "KafkaChannel") + Kind string + + // Group is the API group for the mapped resource kind (like "messaging.knative.dev") + Group string + + // Version is the API version for the mapped resource kind (like "v1alpha1") + Version string +} + +// config Keys for looking up in viper +const ( + keyPluginsDirectory = "plugins.directory" + keySinkMappings = "eventing.sink-mappings" + keyChannelTypeMappings = "eventing.channel-type-mappings" +) + +// legacy config keys, deprecated +const ( + legacyKeyPluginsDirectory = "plugins-dir" + legacyKeySinkMappings = "sink" +) + +// Global (hidden) flags +// TODO: Remove me if decided that they are not needed +const ( + flagPluginsDir = "plugins-dir" +) diff --git a/vendor/knative.dev/client-pkg/pkg/kn/flags/bool.go b/vendor/knative.dev/client-pkg/pkg/kn/flags/bool.go new file mode 100644 index 0000000000..feca0b2af6 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn/flags/bool.go @@ -0,0 +1,126 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package flags + +import ( + "fmt" + "strconv" + "strings" + "unicode" + "unicode/utf8" + + "github.com/spf13/pflag" +) + +var ( + negPrefix = "no-" +) + +// AddBothBoolFlagsUnhidden is just like AddBothBoolFlags but shows both flags. +func AddBothBoolFlagsUnhidden(f *pflag.FlagSet, p *bool, name, short string, value bool, usage string) { + + negativeName := negPrefix + name + + f.BoolVarP(p, name, short, value, usage) + f.Bool(negativeName, !value, InvertUsage(usage)) +} + +// AddBothBoolFlags adds the given flag in both `--foo` and `--no-foo` variants. +// If you do this, make sure you call ReconcileBoolFlags later to catch errors +// and set the relationship between the flag values. Only the flag that does the +// non-default behavior is visible; the other is hidden. +func AddBothBoolFlags(f *pflag.FlagSet, p *bool, name, short string, value bool, usage string) { + AddBothBoolFlagsUnhidden(f, p, name, short, value, usage) + negativeName := negPrefix + name + if value { + err := f.MarkHidden(name) + if err != nil { + panic(err) + } + } else { + err := f.MarkHidden(negativeName) + if err != nil { + panic(err) + } + } +} + +// ReconcileBoolFlags sets the value of the all the "--foo" flags based on +// "--no-foo" if provided, and returns an error if both were provided or an +// explicit value of false was provided to either (as that's confusing). +func ReconcileBoolFlags(f *pflag.FlagSet) error { + var err error + f.VisitAll(func(flag *pflag.Flag) { + // Return early from our comprehension + if err != nil { + return + } + + // Walk the "no-" versions of the flags. Make sure we didn't set + // both, and set the positive value to the opposite of the "no-" + // value if it exists. + if strings.HasPrefix(flag.Name, negPrefix) { + positiveName := flag.Name[len(negPrefix):] + positive := f.Lookup(positiveName) + // Non-paired flag, or wrong types + if positive == nil || positive.Value.Type() != "bool" || flag.Value.Type() != "bool" { + return + } + if flag.Changed { + if positive.Changed { + err = fmt.Errorf("only one of --%s and --%s may be specified", + flag.Name, positiveName) + return + } + err = checkExplicitFalse(flag, positiveName) + if err != nil { + return + } + err = positive.Value.Set("false") + } else { + err = checkExplicitFalse(positive, flag.Name) + } + } + + }) + return err +} + +// checkExplicitFalse returns an error if the flag was explicitly set to false. +func checkExplicitFalse(f *pflag.Flag, betterFlag string) error { + if !f.Changed { + return nil + } + val, err := strconv.ParseBool(f.Value.String()) + if err != nil { + return err + } + if !val { + return fmt.Errorf("use --%s instead of providing \"%s\" to --%s", + betterFlag, f.Value.String(), f.Name) + } + return nil +} + +// FirstCharToLower converts first char in given string to lowercase +func FirstCharToLower(s string) string { + r, n := utf8.DecodeRuneInString(s) + return string(unicode.ToLower(r)) + s[n:] +} + +// InvertUsage inverts the usage string with prefix "Do not" +func InvertUsage(usage string) string { + return "Do not " + FirstCharToLower(usage) +} diff --git a/vendor/knative.dev/client-pkg/pkg/kn/flags/podspec_helper.go b/vendor/knative.dev/client-pkg/pkg/kn/flags/podspec_helper.go new file mode 100644 index 0000000000..4a2dfd127d --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn/flags/podspec_helper.go @@ -0,0 +1,1094 @@ +// 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" + "os" + "strconv" + "strings" + + "k8s.io/apimachinery/pkg/util/intstr" + + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/util/yaml" + + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/sets" + "knative.dev/client-pkg/pkg/util" +) + +// VolumeSourceType is a type standing for enumeration of ConfigMap and Secret +type VolumeSourceType int + +// Enumeration of volume source types: ConfigMap or Secret +const ( + ConfigMapVolumeSourceType VolumeSourceType = iota + SecretVolumeSourceType + EmptyDirVolumeSourceType + PVCVolumeSourceType + PortFormatErr = "the port specification '%s' is not valid. Please provide in the format 'NAME:PORT', where 'NAME' is optional. Examples: '--port h2c:8080' , '--port 8080'." +) + +type MountInfo struct { + VolumeName string + SubPath string + MountOptions string +} + +func (vt VolumeSourceType) String() string { + names := [...]string{"config-map", "secret"} + if vt < ConfigMapVolumeSourceType || vt > SecretVolumeSourceType { + return "unknown" + } + return names[vt] +} + +func containerOfPodSpec(spec *corev1.PodSpec) *corev1.Container { + if len(spec.Containers) == 0 { + newContainer := corev1.Container{} + spec.Containers = append(spec.Containers, newContainer) + } + return &spec.Containers[0] +} + +// UpdateEnvVars gives the configuration all the env var values listed in the given map of +// vars. Does not touch any environment variables not mentioned, but it can add +// new env vars and change the values of existing ones. +func UpdateEnvVars(spec *corev1.PodSpec, allArgs []string, + envToUpdate *util.OrderedMap, envToRemove []string, + envValueFromToUpdate *util.OrderedMap, envValueFromToRemove []string, + envFileName string, envValueFileToUpdate *util.OrderedMap, envValueFileToRemove []string, +) error { + container := containerOfPodSpec(spec) + + allEnvsToUpdate := util.NewOrderedMap() + + envIterator := envToUpdate.Iterator() + envValueFromIterator := envValueFromToUpdate.Iterator() + envValueFileIterator := envValueFileToUpdate.Iterator() + + envKey, envValue, envExists := envIterator.NextString() + envValueFromKey, envValueFromValue, envValueFromExists := envValueFromIterator.NextString() + envValueFileKey, envValueFileValue, envValueFileExists := envValueFileIterator.NextString() + for _, arg := range allArgs { + // envs are stored as NAME=value + if envExists && isValidEnvArg(arg, envKey, envValue) { + allEnvsToUpdate.Set(envKey, corev1.EnvVar{ + Name: envKey, + Value: envValue, + }) + envKey, envValue, envExists = envIterator.NextString() + } else if envValueFromExists && isValidEnvValueFromArg(arg, envValueFromKey, envValueFromValue) { + // envs are stored as NAME=secret:sercretName:key or NAME=config-map:cmName:key + envVarSource, err := createEnvVarSource(envValueFromValue) + if err != nil { + return err + } + allEnvsToUpdate.Set(envValueFromKey, corev1.EnvVar{ + Name: envValueFromKey, + ValueFrom: envVarSource, + }) + envValueFromKey, envValueFromValue, envValueFromExists = envValueFromIterator.NextString() + } else if envValueFileExists && isValidEnvValueFileArg(arg, envFileName) { + for envValueFileExists { + allEnvsToUpdate.Set(envValueFileKey, corev1.EnvVar{ + Name: envValueFileKey, + Value: envValueFileValue, + }) + envValueFileKey, envValueFileValue, envValueFileExists = envValueFileIterator.NextString() + } + } + } + + updated := updateEnvVarsFromMap(container.Env, allEnvsToUpdate) + updated = removeEnvVars(updated, append(envToRemove, envValueFromToRemove...)) + + container.Env = updated + + return nil +} + +// isValidEnvArg checks that the input arg is a valid argument for specifying env value, +// ie. stored as NAME=value +func isValidEnvArg(arg, envKey, envValue string) bool { + return strings.HasPrefix(arg, envKey+"="+envValue) || strings.HasPrefix(arg, "-e="+envKey+"="+envValue) || strings.HasPrefix(arg, "--env="+envKey+"="+envValue) +} + +// isValidEnvValueFromArg checks that the input arg is a valid argument for specifying env from value, +// ie. stored as NAME=secret:sercretName:key or NAME=config-map:cmName:key +func isValidEnvValueFromArg(arg, envValueFromKey, envValueFromValue string) bool { + return strings.HasPrefix(arg, envValueFromKey+"="+envValueFromValue) || strings.HasPrefix(arg, "--env-value-from="+envValueFromKey+"="+envValueFromValue) +} + +// isValidEnvValueFileArg checks that the input arg is a valid argument for specifying env from value, +// ie. stored as NAME=secret:sercretName:key or NAME=config-map:cmName:key +func isValidEnvValueFileArg(arg, envFileName string) bool { + return strings.HasPrefix(arg, envFileName) || strings.HasPrefix(arg, "--env-file="+envFileName) +} + +// UpdateEnvFrom updates envFrom +func UpdateEnvFrom(spec *corev1.PodSpec, toUpdate []string, toRemove []string) error { + container := containerOfPodSpec(spec) + envFrom, err := updateEnvFrom(container.EnvFrom, toUpdate) + if err != nil { + return err + } + container.EnvFrom, err = removeEnvFrom(envFrom, toRemove) + return err +} + +// UpdateVolumeMountsAndVolumes updates the configuration for volume mounts and volumes. +func UpdateVolumeMountsAndVolumes(spec *corev1.PodSpec, + mountsToUpdate *util.OrderedMap, mountsToRemove []string, volumesToUpdate *util.OrderedMap, volumesToRemove []string) error { + container := containerOfPodSpec(spec) + + volumeSourceInfoByName, mountsToUpdate, err := reviseVolumeInfoAndMountsToUpdate(mountsToUpdate, volumesToUpdate) + if err != nil { + return err + } + + volumes, err := updateVolumesFromMap(spec.Volumes, volumeSourceInfoByName) + if err != nil { + return err + } + + volumeMounts, err := updateVolumeMountsFromMap(container.VolumeMounts, mountsToUpdate, volumes) + if err != nil { + return err + } + + volumesToRemove = reviseVolumesToRemove(container.VolumeMounts, volumesToRemove, mountsToRemove) + + container.VolumeMounts = removeVolumeMounts(volumeMounts, mountsToRemove) + spec.Volumes, err = removeVolumes(volumes, volumesToRemove, container.VolumeMounts) + + return err +} + +// UpdateImage a given image +func UpdateImage(spec *corev1.PodSpec, image string) error { + // When not setting the image to a digest, add the user image annotation. + container := containerOfPodSpec(spec) + container.Image = image + return nil +} + +// UpdateContainerCommand updates container with a given argument +func UpdateContainerCommand(spec *corev1.PodSpec, command []string) error { + container := containerOfPodSpec(spec) + container.Command = command + return nil +} + +// UpdateContainerArg updates container with a given argument +func UpdateContainerArg(spec *corev1.PodSpec, arg []string) error { + container := containerOfPodSpec(spec) + container.Args = arg + return nil +} + +// UpdateContainerPort updates container with a given name:port +func UpdateContainerPort(spec *corev1.PodSpec, port string) error { + container := containerOfPodSpec(spec) + + var containerPort int64 + var name string + var err error + + elements := strings.SplitN(port, ":", 2) + if len(elements) == 2 { + name = elements[0] + containerPort, err = strconv.ParseInt(elements[1], 10, 32) + if err != nil { + return fmt.Errorf(PortFormatErr, port) + } + } else { + name = "" + containerPort, err = strconv.ParseInt(elements[0], 10, 32) + if err != nil { + return fmt.Errorf(PortFormatErr, port) + } + } + + container.Ports = []corev1.ContainerPort{{ + ContainerPort: int32(containerPort), + Name: name, + }} + return nil +} + +// UpdateUser updates container with a given user id +func UpdateUser(spec *corev1.PodSpec, user int64) error { + container := containerOfPodSpec(spec) + container.SecurityContext = &corev1.SecurityContext{ + RunAsUser: &user, + } + return nil +} + +// UpdateResources updates container resources for given revision spec +func UpdateResources(spec *corev1.PodSpec, resources corev1.ResourceRequirements, requestsToRemove, limitsToRemove []string) error { + container := containerOfPodSpec(spec) + + if container.Resources.Requests == nil { + container.Resources.Requests = corev1.ResourceList{} + } + + for k, v := range resources.Requests { + container.Resources.Requests[k] = v + } + + for _, reqToRemove := range requestsToRemove { + delete(container.Resources.Requests, corev1.ResourceName(reqToRemove)) + } + + if container.Resources.Limits == nil { + container.Resources.Limits = corev1.ResourceList{} + } + + for k, v := range resources.Limits { + container.Resources.Limits[k] = v + } + + for _, limToRemove := range limitsToRemove { + delete(container.Resources.Limits, corev1.ResourceName(limToRemove)) + } + + return nil +} + +// UpdateServiceAccountName updates the service account name used for the corresponding knative service +func UpdateServiceAccountName(spec *corev1.PodSpec, serviceAccountName string) { + serviceAccountName = strings.TrimSpace(serviceAccountName) + spec.ServiceAccountName = serviceAccountName +} + +// UpdateImagePullSecrets updates the image pull secrets used for the corresponding knative service +func UpdateImagePullSecrets(spec *corev1.PodSpec, pullsecrets string) { + pullsecrets = strings.TrimSpace(pullsecrets) + if pullsecrets == "" { + spec.ImagePullSecrets = nil + } else { + spec.ImagePullSecrets = []corev1.LocalObjectReference{{ + Name: pullsecrets, + }} + } +} + +// UpdateContainers updates the containers array with additional ones provided from file or os.Stdin +func UpdateContainers(spec *corev1.PodSpec, containers []corev1.Container) { + var matched []string + if len(spec.Containers) == 1 { + spec.Containers = append(spec.Containers, containers...) + } else { + for i, container := range spec.Containers { + for j, toUpdate := range containers { + if container.Name == toUpdate.Name { + + spec.Containers[i] = containers[j] + + matched = append(matched, toUpdate.Name) + } + } + } + for _, container := range containers { + if !util.SliceContainsIgnoreCase(matched, container.Name) { + spec.Containers = append(spec.Containers, container) + } + } + } +} + +// UpdateLivenessProbe updates container liveness probe based on provided string +func UpdateLivenessProbe(spec *corev1.PodSpec, probeString string) error { + c := containerOfPodSpec(spec) + handler, err := resolveProbeHandler(probeString) + if err != nil { + return err + } + if c.LivenessProbe == nil { + c.LivenessProbe = &corev1.Probe{} + } + c.LivenessProbe.ProbeHandler = *handler + return nil +} + +// UpdateLivenessProbeOpts updates container liveness probe commons options based on provided string +func UpdateLivenessProbeOpts(spec *corev1.PodSpec, probeString string) error { + c := containerOfPodSpec(spec) + if c.LivenessProbe == nil { + c.LivenessProbe = &corev1.Probe{} + } + err := resolveProbeOptions(c.LivenessProbe, probeString) + if err != nil { + return err + } + return nil +} + +// UpdateReadinessProbe updates container readiness probe based on provided string +func UpdateReadinessProbe(spec *corev1.PodSpec, probeString string) error { + c := containerOfPodSpec(spec) + handler, err := resolveProbeHandler(probeString) + if err != nil { + return err + } + if c.ReadinessProbe == nil { + c.ReadinessProbe = &corev1.Probe{} + } + c.ReadinessProbe.ProbeHandler = *handler + return nil +} + +// UpdateReadinessProbeOpts updates container readiness probe commons options based on provided string +func UpdateReadinessProbeOpts(spec *corev1.PodSpec, probeString string) error { + c := containerOfPodSpec(spec) + if c.ReadinessProbe == nil { + c.ReadinessProbe = &corev1.Probe{} + } + err := resolveProbeOptions(c.ReadinessProbe, probeString) + if err != nil { + return err + } + return nil +} + +// UpdateImagePullPolicy updates the pull policy for the given revision template +func UpdateImagePullPolicy(spec *corev1.PodSpec, imagePullPolicy string) error { + container := containerOfPodSpec(spec) + + if !isValidPullPolicy(imagePullPolicy) { + return fmt.Errorf("invalid --pull-policy %s. Valid arguments (case insensitive): Always | Never | IfNotPresent", imagePullPolicy) + } + container.ImagePullPolicy = getPolicy(imagePullPolicy) + return nil +} + +func getPolicy(policy string) v1.PullPolicy { + var ret v1.PullPolicy + switch strings.ToLower(policy) { + case "always": + ret = v1.PullAlways + case "ifnotpresent": + ret = v1.PullIfNotPresent + case "never": + ret = v1.PullNever + } + return ret +} + +func isValidPullPolicy(policy string) bool { + validPolicies := []string{string(v1.PullAlways), string(v1.PullNever), string(v1.PullIfNotPresent)} + return util.SliceContainsIgnoreCase(validPolicies, policy) +} + +// ======================================================================================= +func updateEnvVarsFromMap(env []corev1.EnvVar, toUpdate *util.OrderedMap) []corev1.EnvVar { + updated := sets.NewString() + + for i := range env { + object, present := toUpdate.Get(env[i].Name) + if present { + env[i] = object.(corev1.EnvVar) + updated.Insert(env[i].Name) + } + } + it := toUpdate.Iterator() + for name, envVar, ok := it.Next(); ok; name, envVar, ok = it.Next() { + if !updated.Has(name) { + env = append(env, envVar.(corev1.EnvVar)) + } + } + return env +} + +func removeEnvVars(env []corev1.EnvVar, toRemove []string) []corev1.EnvVar { + for _, name := range toRemove { + for i, envVar := range env { + if envVar.Name == name { + env = append(env[:i], env[i+1:]...) + break + } + } + } + return env +} + +func createEnvVarSource(spec string) (*corev1.EnvVarSource, error) { + slices := strings.SplitN(spec, ":", 3) + if len(slices) != 3 { + return nil, fmt.Errorf("argument requires a value in form \"resourceType:name:key\" where \"resourceType\" can be one of \"config-map\" (\"cm\") or \"secret\" (\"sc\"); got %q", spec) + } + + typeString := strings.TrimSpace(slices[0]) + sourceName := strings.TrimSpace(slices[1]) + sourceKey := strings.TrimSpace(slices[2]) + + var sourceType string + envVarSource := corev1.EnvVarSource{} + + switch typeString { + case "config-map", "cm": + sourceType = "ConfigMap" + envVarSource.ConfigMapKeyRef = &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: sourceName, + }, + Key: sourceKey} + case "secret", "sc": + sourceType = "Secret" + envVarSource.SecretKeyRef = &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: sourceName, + }, + Key: sourceKey} + default: + return nil, fmt.Errorf("unsupported env source type \"%q\"; supported source types are \"config-map\" (\"cm\") and \"secret\" (\"sc\")", slices[0]) + } + + if len(sourceName) == 0 { + return nil, fmt.Errorf("the name of %s cannot be an empty string", sourceType) + } + + if len(sourceKey) == 0 { + return nil, fmt.Errorf("the key referenced by resource %s \"%s\" cannot be an empty string", sourceType, sourceName) + } + + return &envVarSource, nil +} + +// ======================================================================================= +func updateEnvFrom(envFromSources []corev1.EnvFromSource, toUpdate []string) ([]corev1.EnvFromSource, error) { + existingNameSet := make(map[string]bool) + + for i := range envFromSources { + envSrc := &envFromSources[i] + if canonicalName, err := getCanonicalNameFromEnvFromSource(envSrc); err == nil { + existingNameSet[canonicalName] = true + } + } + + for _, s := range toUpdate { + info, err := newVolumeSourceInfoWithSpecString(s) + if err != nil { + return nil, err + } + + if _, ok := existingNameSet[info.getCanonicalName()]; !ok { + envFromSources = append(envFromSources, *info.createEnvFromSource()) + } + } + + return envFromSources, nil +} + +func removeEnvFrom(envFromSources []corev1.EnvFromSource, toRemove []string) ([]corev1.EnvFromSource, error) { + for _, name := range toRemove { + info, err := newVolumeSourceInfoWithSpecString(name) + if err != nil { + return nil, err + } + for i, envSrc := range envFromSources { + if (info.volumeSourceType == ConfigMapVolumeSourceType && envSrc.ConfigMapRef != nil && info.volumeSourceName == envSrc.ConfigMapRef.Name) || + (info.volumeSourceType == SecretVolumeSourceType && envSrc.SecretRef != nil && info.volumeSourceName == envSrc.SecretRef.Name) { + envFromSources = append(envFromSources[:i], envFromSources[i+1:]...) + break + } + } + } + + if len(envFromSources) == 0 { + envFromSources = nil + } + + return envFromSources, nil +} + +func updateVolume(volume *corev1.Volume, info *volumeSourceInfo) error { + switch info.volumeSourceType { + case ConfigMapVolumeSourceType: + volume.Secret = nil + volume.ConfigMap = &corev1.ConfigMapVolumeSource{LocalObjectReference: corev1.LocalObjectReference{Name: info.volumeSourceName}} + case SecretVolumeSourceType: + volume.ConfigMap = nil + volume.Secret = &corev1.SecretVolumeSource{SecretName: info.volumeSourceName} + case EmptyDirVolumeSourceType: + volume.EmptyDir = &corev1.EmptyDirVolumeSource{Medium: corev1.StorageMedium(info.emptyDirMemoryType), SizeLimit: info.emptyDirSize} + case PVCVolumeSourceType: + volume.PersistentVolumeClaim = &corev1.PersistentVolumeClaimVolumeSource{ClaimName: info.volumeSourceName} + default: + return fmt.Errorf("Invalid VolumeSourceType") + } + return nil +} + +// updateVolumeMountsFromMap updates or adds volume mounts. If a given name of a volume is not existing, it returns an error +func updateVolumeMountsFromMap(volumeMounts []corev1.VolumeMount, toUpdate *util.OrderedMap, volumes []corev1.Volume) ([]corev1.VolumeMount, error) { + set := make(map[string]bool) + + var err error + for i := range volumeMounts { + volumeMount := &volumeMounts[i] + mountInfo, present := toUpdate.Get(volumeMount.MountPath) + + if present { + volumeMountInfo := mountInfo.(*MountInfo) + name := volumeMountInfo.VolumeName + if !existsVolumeNameInVolumes(name, volumes) { + return nil, fmt.Errorf("There is no volume matched with %q", name) + } + volumeMount.ReadOnly, err = isReadOnlyVolume(name, volumeMountInfo.MountOptions, volumes) + if err != nil { + return nil, err + } + volumeMount.Name = name + volumeMount.SubPath = volumeMountInfo.SubPath + set[volumeMount.MountPath] = true + } + } + + it := toUpdate.Iterator() + for mountPath, mountInfo, ok := it.Next(); ok; mountPath, mountInfo, ok = it.Next() { + volumeMountInfo := mountInfo.(*MountInfo) + name := volumeMountInfo.VolumeName + readOnly, err := isReadOnlyVolume(name, volumeMountInfo.MountOptions, volumes) + if err != nil { + return nil, err + } + if !set[mountPath] { + volumeMounts = append(volumeMounts, corev1.VolumeMount{ + Name: name, + ReadOnly: readOnly, + MountPath: mountPath, + SubPath: volumeMountInfo.SubPath, + }) + } + } + + return volumeMounts, nil +} + +func removeVolumeMounts(volumeMounts []corev1.VolumeMount, toRemove []string) []corev1.VolumeMount { + for _, mountPath := range toRemove { + for i, volumeMount := range volumeMounts { + if volumeMount.MountPath == mountPath { + volumeMounts = append(volumeMounts[:i], volumeMounts[i+1:]...) + break + } + } + } + + if len(volumeMounts) == 0 { + return nil + } + + return volumeMounts +} + +// updateVolumesFromMap updates or adds volumes regardless whether the volume is used or not +func updateVolumesFromMap(volumes []corev1.Volume, toUpdate *util.OrderedMap) ([]corev1.Volume, error) { + set := make(map[string]bool) + + for i := range volumes { + volume := &volumes[i] + info, present := toUpdate.Get(volume.Name) + if present { + err := updateVolume(volume, info.(*volumeSourceInfo)) + if err != nil { + return nil, err + } + set[volume.Name] = true + } + } + + it := toUpdate.Iterator() + for name, info, ok := it.Next(); ok; name, info, ok = it.Next() { + if !set[name] { + volumes = append(volumes, corev1.Volume{Name: name}) + updateVolume(&volumes[len(volumes)-1], info.(*volumeSourceInfo)) + } + } + + return volumes, nil +} + +// removeVolumes removes volumes. If there is a volume mount referencing the volume, it causes an error +func removeVolumes(volumes []corev1.Volume, toRemove []string, volumeMounts []corev1.VolumeMount) ([]corev1.Volume, error) { + for _, name := range toRemove { + for i, volume := range volumes { + if volume.Name == name { + if existsVolumeNameInVolumeMounts(name, volumeMounts) { + return nil, fmt.Errorf("The volume %q cannot be removed because it is mounted", name) + } + volumes = append(volumes[:i], volumes[i+1:]...) + break + } + } + } + + if len(volumes) == 0 { + return nil, nil + } + + return volumes, nil +} + +// ======================================================================================= + +type volumeSourceInfo struct { + volumeSourceType VolumeSourceType + volumeSourceName string + emptyDirMemoryType string + emptyDirSize *resource.Quantity +} + +func newVolumeSourceInfoWithSpecString(spec string) (*volumeSourceInfo, error) { + slices := strings.SplitN(spec, ":", 3) + if len(slices) < 2 { + return nil, fmt.Errorf("argument requires a value that contains the : character; got %q, %q", spec, slices) + } + + if len(slices) == 2 { + var volumeSourceType VolumeSourceType + + typeString := strings.TrimSpace(slices[0]) + volumeSourceName := strings.TrimSpace(slices[1]) + + switch typeString { + case "config-map", "cm": + volumeSourceType = ConfigMapVolumeSourceType + case "secret", "sc": + volumeSourceType = SecretVolumeSourceType + case "emptyDir", "ed": + volumeSourceType = EmptyDirVolumeSourceType + case "persistentVolumeClaim", "pvc": + volumeSourceType = PVCVolumeSourceType + default: + return nil, fmt.Errorf("unsupported volume source type \"%q\"; supported volume source types are \"config-map\" and \"secret\"", slices[0]) + } + + if len(volumeSourceName) == 0 { + return nil, fmt.Errorf("the name of %s cannot be an empty string", volumeSourceType) + } + + return &volumeSourceInfo{ + volumeSourceType: volumeSourceType, + volumeSourceName: volumeSourceName, + }, nil + } else { + typeString := strings.TrimSpace(slices[0]) + switch typeString { + case "config-map", "cm", "secret", "sc", "persistentVolumeClaim", "pvc": + return nil, fmt.Errorf("incorrect mount details for type %q", typeString) + case "emptyDir", "ed": + volName := slices[1] + edType, edSize, err := getEmptyDirTypeAndSize(slices[2]) + if err != nil { + return nil, err + } + return &volumeSourceInfo{ + volumeSourceType: EmptyDirVolumeSourceType, + volumeSourceName: volName, + emptyDirMemoryType: edType, + emptyDirSize: edSize, + }, nil + default: + return nil, fmt.Errorf("unsupported volume type \"%q\"; supported volume types are \"config-map or cm\", \"secret or sc\", \"volume or vo\", and \"emptyDir or ed\"", slices[0]) + } + + } +} + +func (vol *volumeSourceInfo) getCanonicalName() string { + return fmt.Sprintf("%s:%s", vol.volumeSourceType, vol.volumeSourceName) +} + +func getCanonicalNameFromEnvFromSource(envSrc *corev1.EnvFromSource) (string, error) { + if envSrc.ConfigMapRef != nil { + return fmt.Sprintf("%s:%s", ConfigMapVolumeSourceType, envSrc.ConfigMapRef.Name), nil + } + if envSrc.SecretRef != nil { + return fmt.Sprintf("%s:%s", SecretVolumeSourceType, envSrc.SecretRef.Name), nil + } + + return "", fmt.Errorf("there is no ConfigMapRef or SecretRef in a EnvFromSource") +} + +func (vol *volumeSourceInfo) createEnvFromSource() *corev1.EnvFromSource { + switch vol.volumeSourceType { + case ConfigMapVolumeSourceType: + return &corev1.EnvFromSource{ + ConfigMapRef: &corev1.ConfigMapEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: vol.volumeSourceName, + }}} + case SecretVolumeSourceType: + return &corev1.EnvFromSource{ + SecretRef: &corev1.SecretEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: vol.volumeSourceName, + }}} + } + + return nil +} + +// ======================================================================================= + +func isReadOnlyVolume(volumeName string, mountOptions string, volumes []corev1.Volume) (bool, error) { + if mountOptions != "" { + options, err := parseMountOptions(mountOptions) + if err != nil { + return false, err + } + if val, ok := options.Get("readonly"); ok && val != "" { + return strconv.ParseBool(val.(string)) + } + } + for _, volume := range volumes { + if volume.Name == volumeName { + return defaultReadOnly(volume), nil + } + } + return true, nil +} + +func parseMountOptions(options string) (*util.OrderedMap, error) { + mountOptions := util.NewOrderedMap() + slices := strings.Split(options, ",") + for _, slice := range slices { + pair := strings.SplitN(slice, "=", 2) + switch strings.ToLower(pair[0]) { + case "readonly": + mountOptions.Set("readonly", pair[1]) + default: + return nil, fmt.Errorf("unknown mount option %q", pair[0]) + } + } + return mountOptions, nil +} + +func defaultReadOnly(volume v1.Volume) bool { + if volume.EmptyDir != nil || volume.PersistentVolumeClaim != nil { + return false + } + return true +} + +func existsVolumeNameInVolumes(volumeName string, volumes []corev1.Volume) bool { + for _, volume := range volumes { + if volume.Name == volumeName { + return true + } + } + return false +} + +func existsVolumeNameInVolumeMounts(volumeName string, volumeMounts []corev1.VolumeMount) bool { + for _, volumeMount := range volumeMounts { + if volumeMount.Name == volumeName { + return true + } + } + return false +} + +// ======================================================================================= + +func getMountInfo(volume string) *MountInfo { + configSlices := strings.SplitN(volume, ":", 2) + var mountInfo MountInfo + if len(configSlices) == 2 { + readOnlySlices := strings.SplitN(configSlices[1], "=", 2) + switch strings.ToLower(readOnlySlices[0]) { + case "readonly": + + } + mountInfo.MountOptions = configSlices[1] + } + slices := strings.SplitN(configSlices[0], "/", 2) + if len(slices) == 1 || slices[1] == "" { + mountInfo.VolumeName = slices[0] + } else { + mountInfo.VolumeName = slices[0] + mountInfo.SubPath = slices[1] + } + return &mountInfo +} + +func reviseVolumeInfoAndMountsToUpdate(mountsToUpdate *util.OrderedMap, volumesToUpdate *util.OrderedMap) (*util.OrderedMap, *util.OrderedMap, error) { + volumeSourceInfoByName := util.NewOrderedMap() //make(map[string]*volumeSourceInfo) + mountsToUpdateRevised := util.NewOrderedMap() //make(map[string]string) + + it := mountsToUpdate.Iterator() + for path, value, ok := it.NextString(); ok; path, value, ok = it.NextString() { + // slices[0] -> config-map, cm, secret, sc, volume, or vo + // slices[1] -> secret, config-map, or volume name + slices := strings.SplitN(value, ":", 2) + if len(slices) == 1 { + mountInfo := getMountInfo(slices[0]) + mountsToUpdateRevised.Set(path, mountInfo) + } else { + switch volumeType := slices[0]; volumeType { + case "config-map", "cm": + generatedName := util.GenerateVolumeName(path) + mountInfo := getMountInfo(slices[1]) + volumeSourceInfoByName.Set(generatedName, &volumeSourceInfo{ + volumeSourceType: ConfigMapVolumeSourceType, + volumeSourceName: mountInfo.VolumeName, + }) + mountInfo.VolumeName = generatedName + mountsToUpdateRevised.Set(path, mountInfo) + case "secret", "sc": + generatedName := util.GenerateVolumeName(path) + mountInfo := getMountInfo(slices[1]) + volumeSourceInfoByName.Set(generatedName, &volumeSourceInfo{ + volumeSourceType: SecretVolumeSourceType, + volumeSourceName: mountInfo.VolumeName, + }) + mountInfo.VolumeName = generatedName + mountsToUpdateRevised.Set(path, mountInfo) + case "emptyDir", "ed": + generatedName := util.GenerateVolumeName(path) + mountInfo := getMountInfo(slices[1]) + volumeSourceInfoByName.Set(generatedName, &volumeSourceInfo{ + volumeSourceType: EmptyDirVolumeSourceType, + volumeSourceName: slices[1], + emptyDirMemoryType: "", + }) + mountInfo.VolumeName = generatedName + mountsToUpdateRevised.Set(path, mountInfo) + case "persistentVolumeClaim", "pvc": + generatedName := util.GenerateVolumeName(path) + mountInfo := getMountInfo(slices[1]) + volumeSourceInfoByName.Set(generatedName, &volumeSourceInfo{ + volumeSourceType: PVCVolumeSourceType, + volumeSourceName: mountInfo.VolumeName, + }) + mountInfo.VolumeName = generatedName + mountsToUpdateRevised.Set(path, mountInfo) + default: + return nil, nil, fmt.Errorf("unsupported volume type \"%q\"; supported volume types are \"config-map or cm\", \"secret or sc\", \"volume or vo\", and \"emptyDir or ed\"", slices[0]) + } + } + } + + it = volumesToUpdate.Iterator() + for name, value, ok := it.NextString(); ok; name, value, ok = it.NextString() { + info, err := newVolumeSourceInfoWithSpecString(value) + if err != nil { + return nil, nil, err + } + volumeSourceInfoByName.Set(name, info) + } + + return volumeSourceInfoByName, mountsToUpdateRevised, nil +} + +func getEmptyDirTypeAndSize(value string) (string, *resource.Quantity, error) { + slices := strings.SplitN(value, ",", 2) + formatErr := fmt.Errorf("incorrect format to specify emptyDir type") + repeatErrStr := "cannot repeat the key %q" + var dirType string + var size *resource.Quantity + switch len(slices) { + case 0: + return "", nil, nil + case 1: + typeSizeSlices := strings.SplitN(slices[0], "=", 2) + if len(typeSizeSlices) < 2 { + return "", nil, formatErr + } + switch strings.ToLower(typeSizeSlices[0]) { + case "type": + dirType = typeSizeSlices[1] + case "size": + quantity, err := resource.ParseQuantity(typeSizeSlices[1]) + if err != nil { + return "", nil, formatErr + } + size = &quantity + default: + return "", nil, formatErr + } + case 2: + for _, slice := range slices { + typeSizeSlices := strings.SplitN(slice, "=", 2) + if len(typeSizeSlices) < 2 { + return "", nil, formatErr + } + switch strings.ToLower(typeSizeSlices[0]) { + case "type": + if dirType != "" { + return "", nil, fmt.Errorf(repeatErrStr, "type") + } + dirType = typeSizeSlices[1] + case "size": + if size != nil { + return "", nil, fmt.Errorf(repeatErrStr, "size") + } + quantity, err := resource.ParseQuantity(typeSizeSlices[1]) + if err != nil { + return "", nil, formatErr + } + size = &quantity + default: + return "", nil, formatErr + } + } + } + return dirType, size, nil +} + +func reviseVolumesToRemove(volumeMounts []corev1.VolumeMount, volumesToRemove []string, mountsToRemove []string) []string { + for _, pathToRemove := range mountsToRemove { + for _, volumeMount := range volumeMounts { + if volumeMount.MountPath == pathToRemove && volumeMount.Name == util.GenerateVolumeName(pathToRemove) { + volumesToRemove = append(volumesToRemove, volumeMount.Name) + } + } + } + return volumesToRemove +} + +func decodeContainersFromFile(filename string) (*corev1.PodSpec, error) { + var f *os.File + var err error + if filename == "-" { + f = os.Stdin + } else { + f, err = os.Open(filename) + if err != nil { + return nil, err + } + } + podSpec := &corev1.PodSpec{} + decoder := yaml.NewYAMLOrJSONDecoder(f, 512) + if err = decoder.Decode(podSpec); err != nil { + return nil, err + } + return podSpec, nil +} + +// ======================================================================================= +// Probes + +// resolveProbe parses probes as a string +// It's split into two functions: +// - resolveProbeOptions() -> common probe opts +// - resolveProbeHandler() -> probe handler [HTTPGet, Exec, TCPSocket] +// Format: +// - [http,https]:host:port:path +// - exec:cmd,cmd,... +// - tcp:host:port +// Common opts (comma separated, case insensitive): +// - InitialDelaySeconds=,FailureThreshold=, +// SuccessThreshold=,PeriodSeconds==,TimeoutSeconds= + +// resolveProbeOptions parses probe commons options +func resolveProbeOptions(probe *corev1.Probe, probeString string) error { + options := strings.Split(probeString, ",") + mappedOptions, err := util.MapFromArray(options, "=") + if err != nil { + return err + } + for k, v := range mappedOptions { + // Trim & verify value is convertible to int + intValue, err := strconv.ParseInt(strings.TrimSpace(v), 0, 32) + if err != nil { + return fmt.Errorf("not a nummeric value for parameter '%s'", k) + } + // Lower case param name mapping + switch strings.TrimSpace(strings.ToLower(k)) { + case "initialdelayseconds": + probe.InitialDelaySeconds = int32(intValue) + case "timeoutseconds": + probe.TimeoutSeconds = int32(intValue) + case "periodseconds": + probe.PeriodSeconds = int32(intValue) + case "successthreshold": + probe.SuccessThreshold = int32(intValue) + case "failurethreshold": + probe.FailureThreshold = int32(intValue) + default: + return fmt.Errorf("not a valid probe parameter name '%s'", k) + } + } + return nil +} + +// resolveProbeHandler parses probe handler options +func resolveProbeHandler(probeString string) (*corev1.ProbeHandler, error) { + if len(probeString) == 0 { + return nil, fmt.Errorf("no probe parameters detected") + } + probeParts := strings.Split(probeString, ":") + if len(probeParts) > 4 { + return nil, fmt.Errorf("too many probe parameters provided, please check the format") + } + var probeHandler *corev1.ProbeHandler + switch probeParts[0] { + case "http", "https": + if len(probeParts) != 4 { + return nil, fmt.Errorf("unexpected probe format, please use 'http:host:port:path'") + } + handler := corev1.ProbeHandler{ + HTTPGet: &corev1.HTTPGetAction{}, + } + if probeParts[0] == "https" { + handler.HTTPGet.Scheme = v1.URISchemeHTTPS + } + handler.HTTPGet.Host = probeParts[1] + if probeParts[2] != "" { + // Cosmetic fix to have default 'port: 0' instead of empty string 'port: ""' + handler.HTTPGet.Port = intstr.Parse(probeParts[2]) + } + handler.HTTPGet.Path = probeParts[3] + + probeHandler = &handler + case "exec": + if len(probeParts) != 2 { + return nil, fmt.Errorf("unexpected probe format, please use 'exec:[,,...]'") + } + if len(probeParts[1]) == 0 { + return nil, fmt.Errorf("at least one command parameter is required for Exec probe") + } + handler := corev1.ProbeHandler{ + Exec: &corev1.ExecAction{}, + } + cmd := strings.Split(probeParts[1], ",") + handler.Exec.Command = cmd + + probeHandler = &handler + case "tcp": + if len(probeParts) != 3 { + return nil, fmt.Errorf("unexpected probe format, please use 'tcp:host:port") + } + handler := corev1.ProbeHandler{ + TCPSocket: &corev1.TCPSocketAction{}, + } + handler.TCPSocket.Host = probeParts[1] + handler.TCPSocket.Port = intstr.Parse(probeParts[2]) + + probeHandler = &handler + default: + return nil, fmt.Errorf("unsupported probe type '%s'; supported types: http, https, exec, tcp", probeParts[0]) + } + return probeHandler, nil +} + +// ======================================================================================= diff --git a/vendor/knative.dev/client-pkg/pkg/kn/plugin/types.go b/vendor/knative.dev/client-pkg/pkg/kn/plugin/types.go new file mode 100644 index 0000000000..1d740b9a54 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/kn/plugin/types.go @@ -0,0 +1,30 @@ +package plugin + +// Allow plugins to register to this slice for inlining +var InternalPlugins PluginList + +// Interface describing a plugin +type Plugin interface { + // Get the name of the plugin (the file name without extensions) + Name() string + + // Execute the plugin with the given arguments + Execute(args []string) error + + // Return a description of the plugin (if support by the plugin binary) + Description() (string, error) + + // The command path leading to this plugin. + // Eg. for a plugin "kn source github" this will be [ "source", "github" ] + CommandParts() []string + + // Location of the plugin where it is stored in the filesystem + Path() string +} + +// Used for sorting a list of plugins +type PluginList []Plugin + +func (p PluginList) Len() int { return len(p) } +func (p PluginList) Less(i, j int) bool { return p[i].Name() < p[j].Name() } +func (p PluginList) Swap(i, j int) { p[i], p[j] = p[j], p[i] } diff --git a/vendor/knative.dev/client-pkg/pkg/messaging/v1/channels_client.go b/vendor/knative.dev/client-pkg/pkg/messaging/v1/channels_client.go new file mode 100644 index 0000000000..5a4beb5a28 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/messaging/v1/channels_client.go @@ -0,0 +1,165 @@ +// 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/client-pkg/pkg/util" + eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" + "knative.dev/eventing/pkg/client/clientset/versioned/scheme" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + messagingv1 "knative.dev/eventing/pkg/apis/messaging/v1" + clientmessagingv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/messaging/v1" + + knerrors "knative.dev/client-pkg/pkg/errors" +) + +// KnChannelsClient for interacting with Channels +type KnChannelsClient interface { + + // GetChannel returns a Channel by its name + GetChannel(ctx context.Context, name string) (*messagingv1.Channel, error) + + // CreteChannel creates a Channel with given spec + CreateChannel(ctx context.Context, channel *messagingv1.Channel) error + + // DeleteChannel deletes a Channel by its name + DeleteChannel(ctx context.Context, name string) error + + // ListChannel lists all Channels + ListChannel(ctx context.Context) (*messagingv1.ChannelList, error) + + // Namespace returns the namespace for this channel client + Namespace() string +} + +// channelsClient struct holds the client interface and namespace +type channelsClient struct { + client clientmessagingv1.ChannelInterface + namespace string +} + +// newKnChannelsClient returns kn channels client +func newKnChannelsClient(client clientmessagingv1.ChannelInterface, namespace string) KnChannelsClient { + return &channelsClient{ + client: client, + namespace: namespace, + } +} + +// Get the namespace for which this client is created +func (c *channelsClient) Namespace() string { + return c.namespace +} + +// GetChannel gets Channel by its name +func (c *channelsClient) GetChannel(ctx context.Context, name string) (*messagingv1.Channel, error) { + channel, err := c.client.Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + err = updateMessagingGVK(channel) + if err != nil { + return nil, err + } + return channel, nil +} + +// CreateChannel creates Channel with given spec +func (c *channelsClient) CreateChannel(ctx context.Context, channel *messagingv1.Channel) error { + _, err := c.client.Create(ctx, channel, metav1.CreateOptions{}) + return knerrors.GetError(err) +} + +// DeleteChannel deletes Channel by its name +func (c *channelsClient) DeleteChannel(ctx context.Context, name string) error { + return knerrors.GetError(c.client.Delete(ctx, name, metav1.DeleteOptions{})) +} + +// ListChannel lists channels in configured namespace +func (c *channelsClient) ListChannel(ctx context.Context) (*messagingv1.ChannelList, error) { + channelList, err := c.client.List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + + return updateChannelListGVK(channelList) +} + +func updateChannelListGVK(channelList *messagingv1.ChannelList) (*messagingv1.ChannelList, error) { + channelListNew := channelList.DeepCopy() + err := updateMessagingGVK(channelListNew) + if err != nil { + return nil, err + } + + channelListNew.Items = make([]messagingv1.Channel, len(channelList.Items)) + for idx, channel := range channelList.Items { + channelClone := channel.DeepCopy() + err := updateMessagingGVK(channelClone) + if err != nil { + return nil, err + } + channelListNew.Items[idx] = *channelClone + } + return channelListNew, nil +} + +// ChannelBuilder is for building the Channel object +type ChannelBuilder struct { + channel *messagingv1.Channel +} + +// NewChannelBuilder for building Channel object +func NewChannelBuilder(name, namespace string) *ChannelBuilder { + return &ChannelBuilder{channel: &messagingv1.Channel{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + }} +} + +// WithGvk sets the GVK on the channel +func (c *ChannelBuilder) WithGvk() *ChannelBuilder { + _ = util.UpdateGroupVersionKindWithScheme(c.channel, eventingv1.SchemeGroupVersion, scheme.Scheme) + return c +} + +// Type sets the type of the channel to create +func (c *ChannelBuilder) Type(gvk *schema.GroupVersionKind) *ChannelBuilder { + if gvk == nil { + return c + } + + c.channel.TypeMeta = metav1.TypeMeta{ + APIVersion: gvk.GroupVersion().String(), + Kind: gvk.Kind, + } + + spec := &messagingv1.ChannelTemplateSpec{} + spec.Kind = gvk.Kind + spec.APIVersion = gvk.GroupVersion().String() + c.channel.Spec.ChannelTemplate = spec + return c +} + +// Build returns the Channel object from the builder +func (c *ChannelBuilder) Build() *messagingv1.Channel { + return c.channel +} diff --git a/vendor/knative.dev/client-pkg/pkg/messaging/v1/channels_client_mock.go b/vendor/knative.dev/client-pkg/pkg/messaging/v1/channels_client_mock.go new file mode 100644 index 0000000000..bb7120e2a4 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/messaging/v1/channels_client_mock.go @@ -0,0 +1,108 @@ +// 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" + "testing" + + messagingv1 "knative.dev/eventing/pkg/apis/messaging/v1" + + "knative.dev/client-pkg/pkg/util/mock" +) + +type MockKnChannelsClient struct { + t *testing.T + recorder *ChannelsRecorder +} + +// NewMockKnChannelsClient returns a new mock instance which you need to record for +func NewMockKnChannelsClient(t *testing.T, ns ...string) *MockKnChannelsClient { + namespace := "default" + if len(ns) > 0 { + namespace = ns[0] + } + return &MockKnChannelsClient{ + t: t, + recorder: &ChannelsRecorder{mock.NewRecorder(t, namespace)}, + } +} + +// Ensure that the interface is implemented +var _ KnChannelsClient = &MockKnChannelsClient{} + +// recorder for service +type ChannelsRecorder struct { + r *mock.Recorder +} + +// Recorder returns the recorder for registering API calls +func (c *MockKnChannelsClient) Recorder() *ChannelsRecorder { + return c.recorder +} + +// Namespace of this client +func (c *MockKnChannelsClient) Namespace() string { + return c.recorder.r.Namespace() +} + +// CreateChannel records a call for CreateChannel with the expected error +func (sr *ChannelsRecorder) CreateChannel(channels interface{}, err error) { + sr.r.Add("CreateChannel", []interface{}{channels}, []interface{}{err}) +} + +// CreateChannel performs a previously recorded action, failing if non has been registered +func (c *MockKnChannelsClient) CreateChannel(ctx context.Context, channels *messagingv1.Channel) error { + call := c.recorder.r.VerifyCall("CreateChannel", channels) + return mock.ErrorOrNil(call.Result[0]) +} + +// GetChannel records a call for GetChannel with the expected object or error. Either channels or err should be nil +func (sr *ChannelsRecorder) GetChannel(name interface{}, channels *messagingv1.Channel, err error) { + sr.r.Add("GetChannel", []interface{}{name}, []interface{}{channels, err}) +} + +// GetChannel performs a previously recorded action, failing if non has been registered +func (c *MockKnChannelsClient) GetChannel(ctx context.Context, name string) (*messagingv1.Channel, error) { + call := c.recorder.r.VerifyCall("GetChannel", name) + return call.Result[0].(*messagingv1.Channel), mock.ErrorOrNil(call.Result[1]) +} + +// DeleteChannel records a call for DeleteChannel with the expected error (nil if none) +func (sr *ChannelsRecorder) DeleteChannel(name interface{}, err error) { + sr.r.Add("DeleteChannel", []interface{}{name}, []interface{}{err}) +} + +// DeleteChannel performs a previously recorded action, failing if non has been registered +func (c *MockKnChannelsClient) DeleteChannel(ctx context.Context, name string) error { + call := c.recorder.r.VerifyCall("DeleteChannel", name) + return mock.ErrorOrNil(call.Result[0]) +} + +// ListChannel records a call for ListChannel with the expected error (nil if none) +func (sr *ChannelsRecorder) ListChannel(channelsList *messagingv1.ChannelList, err error) { + sr.r.Add("ListChannel", []interface{}{}, []interface{}{channelsList, err}) +} + +// ListChannel performs a previously recorded action, failing if non has been registered +func (c *MockKnChannelsClient) ListChannel(context.Context) (*messagingv1.ChannelList, error) { + call := c.recorder.r.VerifyCall("ListChannel") + return call.Result[0].(*messagingv1.ChannelList), mock.ErrorOrNil(call.Result[1]) +} + +// Validates validates whether every recorded action has been called +func (sr *ChannelsRecorder) Validate() { + sr.r.CheckThatAllRecordedMethodsHaveBeenCalled() +} diff --git a/vendor/knative.dev/client-pkg/pkg/messaging/v1/client.go b/vendor/knative.dev/client-pkg/pkg/messaging/v1/client.go new file mode 100644 index 0000000000..eeadc12e52 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/messaging/v1/client.go @@ -0,0 +1,71 @@ +// 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 ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + messagingv1 "knative.dev/eventing/pkg/apis/messaging/v1" + "knative.dev/eventing/pkg/client/clientset/versioned/scheme" + clientv1beta1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/messaging/v1" + + "knative.dev/client-pkg/pkg/util" +) + +// KnMessagingClient to Eventing Messaging. All methods are relative to +// the namespace specified during construction +type KnMessagingClient interface { + // Get the Channels client + ChannelsClient() KnChannelsClient + + // Get the Subscriptions client + SubscriptionsClient() KnSubscriptionsClient +} + +// messagingClient holds Messaging client interface and namespace +type messagingClient struct { + client clientv1beta1.MessagingV1Interface + namespace string +} + +// NewKnMessagingClient for managing all eventing messaging types +func NewKnMessagingClient(client clientv1beta1.MessagingV1Interface, namespace string) KnMessagingClient { + return &messagingClient{ + client: client, + namespace: namespace, + } +} + +// ChannelsClient for working with Channels +func (c *messagingClient) ChannelsClient() KnChannelsClient { + return newKnChannelsClient(c.client.Channels(c.namespace), c.namespace) +} + +// SubscriptionsClient for working with Subscriptions +func (c *messagingClient) SubscriptionsClient() KnSubscriptionsClient { + return newKnSubscriptionsClient(c.client.Subscriptions(c.namespace), c.namespace) +} + +// update GVK of object +func updateMessagingGVK(obj runtime.Object) error { + return util.UpdateGroupVersionKindWithScheme(obj, messagingv1.SchemeGroupVersion, scheme.Scheme) +} + +// BuiltInChannelGVKs returns the GVKs for built in channel +func BuiltInChannelGVKs() []schema.GroupVersionKind { + return []schema.GroupVersionKind{ + messagingv1.SchemeGroupVersion.WithKind("InMemoryChannel"), + } +} diff --git a/vendor/knative.dev/client-pkg/pkg/messaging/v1/subscriptions_client.go b/vendor/knative.dev/client-pkg/pkg/messaging/v1/subscriptions_client.go new file mode 100644 index 0000000000..61c4dc5bfc --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/messaging/v1/subscriptions_client.go @@ -0,0 +1,235 @@ +/* +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/client-pkg/pkg/config" + + "k8s.io/client-go/util/retry" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + eventingduckv1 "knative.dev/eventing/pkg/apis/duck/v1" + messagingv1 "knative.dev/eventing/pkg/apis/messaging/v1" + clientmessagingv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/messaging/v1" + duckv1 "knative.dev/pkg/apis/duck/v1" + + knerrors "knative.dev/client-pkg/pkg/errors" +) + +type SubscriptionUpdateFunc func(origSub *messagingv1.Subscription) (*messagingv1.Subscription, error) + +// KnSubscriptionsClient for interacting with Subscriptions +type KnSubscriptionsClient interface { + + // GetSubscription returns a Subscription by its name + GetSubscription(ctx context.Context, name string) (*messagingv1.Subscription, error) + + // CreateSubscription creates a Subscription with given spec + CreateSubscription(ctx context.Context, subscription *messagingv1.Subscription) error + + // UpdateSubscription updates a Subscription with given spec + UpdateSubscription(ctx context.Context, subscription *messagingv1.Subscription) error + + // UpdateSubscriptionWithRetry updates a Subscription and retries on conflict error + UpdateSubscriptionWithRetry(ctx context.Context, name string, updateFunc SubscriptionUpdateFunc, nrRetries int) error + + // DeleteSubscription deletes a Subscription by its name + DeleteSubscription(ctx context.Context, name string) error + + // ListSubscription lists all Subscriptions + ListSubscription(ctx context.Context) (*messagingv1.SubscriptionList, error) + + // Namespace returns the namespace for this subscription client + Namespace() string +} + +// subscriptionsClient struct holds the client interface and namespace +type subscriptionsClient struct { + client clientmessagingv1.SubscriptionInterface + namespace string +} + +// newKnSubscriptionsClient returns kn subscriptions client +func newKnSubscriptionsClient(client clientmessagingv1.SubscriptionInterface, namespace string) KnSubscriptionsClient { + return &subscriptionsClient{ + client: client, + namespace: namespace, + } +} + +// Get the namespace for which this client is created +func (c *subscriptionsClient) Namespace() string { + return c.namespace +} + +// GetSubscription gets Subscription by its name +func (c *subscriptionsClient) GetSubscription(ctx context.Context, name string) (*messagingv1.Subscription, error) { + subscription, err := c.client.Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + err = updateMessagingGVK(subscription) + if err != nil { + return nil, err + } + return subscription, nil +} + +// CreateSubscription creates Subscription with given spec +func (c *subscriptionsClient) CreateSubscription(ctx context.Context, subscription *messagingv1.Subscription) error { + _, err := c.client.Create(ctx, subscription, metav1.CreateOptions{}) + return knerrors.GetError(err) +} + +// UpdateSubscription creates Subscription with given spec +func (c *subscriptionsClient) UpdateSubscription(ctx context.Context, subscription *messagingv1.Subscription) error { + _, err := c.client.Update(ctx, subscription, metav1.UpdateOptions{}) + return knerrors.GetError(err) +} + +func (c *subscriptionsClient) UpdateSubscriptionWithRetry(ctx context.Context, name string, updateFunc SubscriptionUpdateFunc, nrRetries int) error { + return updateSubscriptionWithRetry(ctx, c, name, updateFunc, nrRetries) +} + +func updateSubscriptionWithRetry(ctx context.Context, c KnSubscriptionsClient, name string, updateFunc SubscriptionUpdateFunc, nrRetries int) error { + b := config.DefaultRetry + b.Steps = nrRetries + err := retry.RetryOnConflict(b, func() error { + return updateSubscription(ctx, c, name, updateFunc) + }) + return err +} + +func updateSubscription(ctx context.Context, c KnSubscriptionsClient, name string, updateFunc SubscriptionUpdateFunc) error { + sub, err := c.GetSubscription(ctx, name) + if err != nil { + return err + } + if sub.GetDeletionTimestamp() != nil { + return fmt.Errorf("can't update subscription %s because it has been marked for deletion", name) + } + updatedSub, err := updateFunc(sub.DeepCopy()) + if err != nil { + return err + } + + return c.UpdateSubscription(ctx, updatedSub) +} + +// DeleteSubscription deletes Subscription by its name +func (c *subscriptionsClient) DeleteSubscription(ctx context.Context, name string) error { + return knerrors.GetError(c.client.Delete(ctx, name, metav1.DeleteOptions{})) +} + +// ListSubscription lists subscriptions in configured namespace +func (c *subscriptionsClient) ListSubscription(ctx context.Context) (*messagingv1.SubscriptionList, error) { + subscriptionList, err := c.client.List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + + return updateSubscriptionListGVK(subscriptionList) +} + +func updateSubscriptionListGVK(subscriptionList *messagingv1.SubscriptionList) (*messagingv1.SubscriptionList, error) { + subscriptionListNew := subscriptionList.DeepCopy() + err := updateMessagingGVK(subscriptionListNew) + if err != nil { + return nil, err + } + + subscriptionListNew.Items = make([]messagingv1.Subscription, len(subscriptionList.Items)) + for idx, subscription := range subscriptionList.Items { + subscriptionClone := subscription.DeepCopy() + err := updateMessagingGVK(subscriptionClone) + if err != nil { + return nil, err + } + subscriptionListNew.Items[idx] = *subscriptionClone + } + return subscriptionListNew, nil +} + +// SubscriptionBuilder is for building the Subscription object +type SubscriptionBuilder struct { + subscription *messagingv1.Subscription +} + +// NewSubscriptionBuilder for building Subscription object +func NewSubscriptionBuilder(name string) *SubscriptionBuilder { + return &SubscriptionBuilder{subscription: &messagingv1.Subscription{ + TypeMeta: metav1.TypeMeta{ + APIVersion: messagingv1.SchemeGroupVersion.String(), + Kind: "Subscription", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + }} +} + +// NewSubscriptionBuilderFromExisting for building Subscription object from existing Subscription object +func NewSubscriptionBuilderFromExisting(subs *messagingv1.Subscription) *SubscriptionBuilder { + return &SubscriptionBuilder{subscription: subs.DeepCopy()} +} + +// Channel sets the channel reference for this subscription +func (s *SubscriptionBuilder) Channel(channel *duckv1.KReference) *SubscriptionBuilder { + if channel == nil { + return s + } + + s.subscription.Spec.Channel = *channel + return s +} + +func (s *SubscriptionBuilder) Subscriber(subs *duckv1.Destination) *SubscriptionBuilder { + if subs == nil { + return s + } + + s.subscription.Spec.Subscriber = subs + return s +} + +func (s *SubscriptionBuilder) Reply(reply *duckv1.Destination) *SubscriptionBuilder { + if reply == nil { + return s + } + + s.subscription.Spec.Reply = reply + return s +} + +func (s *SubscriptionBuilder) DeadLetterSink(dls *duckv1.Destination) *SubscriptionBuilder { + if dls == nil { + return s + } + + ds := &eventingduckv1.DeliverySpec{} + ds.DeadLetterSink = dls + s.subscription.Spec.Delivery = ds + return s +} + +// Build returns the Subscription object from the builder +func (s *SubscriptionBuilder) Build() *messagingv1.Subscription { + return s.subscription +} diff --git a/vendor/knative.dev/client-pkg/pkg/messaging/v1/subscriptions_client_mock.go b/vendor/knative.dev/client-pkg/pkg/messaging/v1/subscriptions_client_mock.go new file mode 100644 index 0000000000..1f84ad8c9f --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/messaging/v1/subscriptions_client_mock.go @@ -0,0 +1,127 @@ +/* +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" + "testing" + + messagingv1 "knative.dev/eventing/pkg/apis/messaging/v1" + + "knative.dev/client-pkg/pkg/util/mock" +) + +type MockKnSubscriptionsClient struct { + t *testing.T + recorder *SubscriptionsRecorder + namespace string +} + +// NewMockKnSubscriptionsClient returns a new mock instance which you need to record for +func NewMockKnSubscriptionsClient(t *testing.T, ns ...string) *MockKnSubscriptionsClient { + namespace := "default" + if len(ns) > 0 { + namespace = ns[0] + } + return &MockKnSubscriptionsClient{ + t: t, + recorder: &SubscriptionsRecorder{mock.NewRecorder(t, namespace)}, + namespace: namespace, + } +} + +// Ensure that the interface is implemented +var _ KnSubscriptionsClient = &MockKnSubscriptionsClient{} + +// recorder for service +type SubscriptionsRecorder struct { + r *mock.Recorder +} + +// Recorder returns the recorder for registering API calls +func (c *MockKnSubscriptionsClient) Recorder() *SubscriptionsRecorder { + return c.recorder +} + +// Namespace of this client +func (c *MockKnSubscriptionsClient) Namespace() string { + return c.recorder.r.Namespace() +} + +// CreateSubscription records a call for CreateSubscription with the expected error +func (sr *SubscriptionsRecorder) CreateSubscription(subscription interface{}, err error) { + sr.r.Add("CreateSubscription", []interface{}{subscription}, []interface{}{err}) +} + +// CreateSubscription performs a previously recorded action, failing if non has been registered +func (c *MockKnSubscriptionsClient) CreateSubscription(ctx context.Context, subscription *messagingv1.Subscription) error { + call := c.recorder.r.VerifyCall("CreateSubscription", subscription) + return mock.ErrorOrNil(call.Result[0]) +} + +// GetSubscription records a call for GetSubscription with the expected object or error. Either subscriptions or err should be nil +func (sr *SubscriptionsRecorder) GetSubscription(name interface{}, subscription *messagingv1.Subscription, err error) { + sr.r.Add("GetSubscription", []interface{}{name}, []interface{}{subscription, err}) +} + +// GetSubscription performs a previously recorded action, failing if non has been registered +func (c *MockKnSubscriptionsClient) GetSubscription(ctx context.Context, name string) (*messagingv1.Subscription, error) { + call := c.recorder.r.VerifyCall("GetSubscription", name) + return call.Result[0].(*messagingv1.Subscription), mock.ErrorOrNil(call.Result[1]) +} + +// DeleteSubscription records a call for DeleteSubscription with the expected error (nil if none) +func (sr *SubscriptionsRecorder) DeleteSubscription(name interface{}, err error) { + sr.r.Add("DeleteSubscription", []interface{}{name}, []interface{}{err}) +} + +// DeleteSubscription performs a previously recorded action, failing if non has been registered +func (c *MockKnSubscriptionsClient) DeleteSubscription(ctx context.Context, name string) error { + call := c.recorder.r.VerifyCall("DeleteSubscription", name) + return mock.ErrorOrNil(call.Result[0]) +} + +// ListSubscription records a call for ListSubscription with the expected error (nil if none) +func (sr *SubscriptionsRecorder) ListSubscription(subscriptionsList *messagingv1.SubscriptionList, err error) { + sr.r.Add("ListSubscription", []interface{}{}, []interface{}{subscriptionsList, err}) +} + +// ListSubscription performs a previously recorded action, failing if non has been registered +func (c *MockKnSubscriptionsClient) ListSubscription(context.Context) (*messagingv1.SubscriptionList, error) { + call := c.recorder.r.VerifyCall("ListSubscription") + return call.Result[0].(*messagingv1.SubscriptionList), mock.ErrorOrNil(call.Result[1]) +} + +// UpdateSubscription records a call for CreateSubscription with the expected error +func (sr *SubscriptionsRecorder) UpdateSubscription(subscription interface{}, err error) { + sr.r.Add("UpdateSubscription", []interface{}{subscription}, []interface{}{err}) +} + +// UpdateSubscription performs a previously recorded action, failing if non has been registered +func (c *MockKnSubscriptionsClient) UpdateSubscription(ctx context.Context, subscription *messagingv1.Subscription) error { + call := c.recorder.r.VerifyCall("UpdateSubscription", subscription) + return mock.ErrorOrNil(call.Result[0]) +} + +func (c *MockKnSubscriptionsClient) UpdateSubscriptionWithRetry(ctx context.Context, name string, updateFunc SubscriptionUpdateFunc, nrRetries int) error { + return updateSubscriptionWithRetry(ctx, c, name, updateFunc, nrRetries) +} + +// Validates validates whether every recorded action has been called +func (sr *SubscriptionsRecorder) Validate() { + sr.r.CheckThatAllRecordedMethodsHaveBeenCalled() +} diff --git a/vendor/knative.dev/client-pkg/pkg/printers/interface.go b/vendor/knative.dev/client-pkg/pkg/printers/interface.go new file mode 100644 index 0000000000..517ff2391a --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/printers/interface.go @@ -0,0 +1,44 @@ +/* +Copyright 2017 The Kubernetes 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. +*/ + +// The following is a subset of original implementation +// at https://github.com/kubernetes/kubernetes/blob/v1.15.0-alpha.2/pkg/printers/interface.go + +package printers + +import ( + "io" + + "k8s.io/apimachinery/pkg/runtime" +) + +// ResourcePrinter is an interface that knows how to print runtime objects. +type ResourcePrinter interface { + // Print receives a runtime object, formats it and prints it to a writer. + PrintObj(runtime.Object, io.Writer) error +} + +// ResourcePrinterFunc is a function that can print objects +type ResourcePrinterFunc func(runtime.Object, io.Writer) error + +// PrintObj implements ResourcePrinter +func (fn ResourcePrinterFunc) PrintObj(obj runtime.Object, w io.Writer) error { + return fn(obj, w) +} + +// PrintOptions for different table printing options +type PrintOptions struct { + NoHeaders bool + //TODO: Add options for eg: with-kind, server-printing, wide etc + AllNamespaces bool +} diff --git a/vendor/knative.dev/client-pkg/pkg/printers/prefixwriter.go b/vendor/knative.dev/client-pkg/pkg/printers/prefixwriter.go new file mode 100644 index 0000000000..fd392e7668 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/printers/prefixwriter.go @@ -0,0 +1,126 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package printers + +import ( + "fmt" + "io" + "strings" + "text/tabwriter" +) + +type flusher interface { + Flush() error +} + +func NewBarePrefixWriter(out io.Writer) PrefixWriter { + return &prefixWriter{out: out, nested: nil, colIndent: 0, spaceIndent: 0} +} + +// NewPrefixWriter creates a new PrefixWriter. +func NewPrefixWriter(out io.Writer) PrefixWriter { + tabWriter := tabwriter.NewWriter(out, 0, 8, 2, ' ', 0) + return &prefixWriter{out: tabWriter, nested: nil, colIndent: 0, spaceIndent: 0} +} + +// PrefixWriter can write text at various indentation levels. +type PrefixWriter interface { + // Write writes text with the specified indentation level. + Writef(format string, a ...interface{}) + // WriteLine writes an entire line with no indentation level. + WriteLine(a ...interface{}) + // Write columns with an initial indentation + WriteCols(cols ...string) PrefixWriter + // Write columns with an initial indentation and a newline at the end + WriteColsLn(cols ...string) PrefixWriter + // Flush forces indentation to be reset. + Flush() error + // WriteAttribute writes the attr (as a label) with the given value and returns + // a PrefixWriter for writing any subattributes. + WriteAttribute(attr, value string) PrefixWriter +} + +// prefixWriter implements PrefixWriter +type prefixWriter struct { + out io.Writer + nested PrefixWriter + colIndent int + spaceIndent int +} + +var _ PrefixWriter = &prefixWriter{} + +func (pw *prefixWriter) Writef(format string, a ...interface{}) { + prefix := "" + levelSpace := " " + for i := 0; i < pw.spaceIndent; i++ { + prefix += levelSpace + } + levelTab := "\t" + for i := 0; i < pw.colIndent; i++ { + prefix += levelTab + } + if pw.nested != nil { + pw.nested.Writef(prefix+format, a...) + } else { + fmt.Fprintf(pw.out, prefix+format, a...) + } +} + +func (pw *prefixWriter) WriteCols(cols ...string) PrefixWriter { + ss := make([]string, len(cols)) + for i := range cols { + ss[i] = "%s" + } + format := strings.Join(ss, "\t") + s := make([]interface{}, len(cols)) + for i, v := range cols { + s[i] = v + } + + pw.Writef(format, s...) + return &prefixWriter{pw.out, pw, 1, 0} +} + +// WriteCols writes the columns to the writer and returns a PrefixWriter for +// writing any further parts of the "record" in the last column. +func (pw *prefixWriter) WriteColsLn(cols ...string) PrefixWriter { + ret := pw.WriteCols(cols...) + pw.WriteLine() + return ret +} + +func (pw *prefixWriter) WriteLine(a ...interface{}) { + fmt.Fprintln(pw.out, a...) +} + +// WriteAttribute writes the attr (as a label) with the given value and returns +// a PrefixWriter for writing any subattributes. +func (pw *prefixWriter) WriteAttribute(attr, value string) PrefixWriter { + pw.WriteColsLn(Label(attr), value) + return &prefixWriter{pw.out, pw, 0, 1} +} + +func (pw *prefixWriter) Flush() error { + if f, ok := pw.out.(flusher); ok { + return f.Flush() + } + return fmt.Errorf("output stream %v doesn't support Flush", pw.out) +} + +// Format label (extracted so that color could be added more easily to all labels) +func Label(label string) string { + return label + ":" +} diff --git a/vendor/knative.dev/client-pkg/pkg/printers/tablegenerator.go b/vendor/knative.dev/client-pkg/pkg/printers/tablegenerator.go new file mode 100644 index 0000000000..27fd94be4c --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/printers/tablegenerator.go @@ -0,0 +1,147 @@ +/* +Copyright 2019 The Kubernetes 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. +*/ + +// The following is a subset of original implementation +// at https://github.com/kubernetes/kubernetes/blob/v1.15.0-alpha.2/pkg/printers/tablegenerator.go + +package printers + +import ( + "fmt" + "reflect" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +type TableGenerator interface { + GenerateTable(obj runtime.Object, options PrintOptions) (*metav1beta1.Table, error) +} + +type PrintHandler interface { + TableHandler(columns []metav1beta1.TableColumnDefinition, printFunc interface{}) error +} + +type handlerEntry struct { + columnDefinitions []metav1beta1.TableColumnDefinition + printFunc reflect.Value +} + +// HumanReadablePrinter is an implementation of ResourcePrinter which attempts to provide +// more elegant output. +type HumanReadablePrinter struct { + handlerMap map[reflect.Type]*handlerEntry + options PrintOptions +} + +var _ TableGenerator = &HumanReadablePrinter{} +var _ PrintHandler = &HumanReadablePrinter{} + +// NewTableGenerator creates a HumanReadablePrinter suitable for calling GenerateTable(). +func NewTableGenerator() *HumanReadablePrinter { + return &HumanReadablePrinter{ + handlerMap: make(map[reflect.Type]*handlerEntry), + } +} + +// GenerateTable returns a table for the provided object, using the printer registered for that type. It returns +// a table that includes all of the information requested by options, but will not remove rows or columns. The +// caller is responsible for applying rules related to filtering rows or columns. +func (h *HumanReadablePrinter) GenerateTable(obj runtime.Object, options PrintOptions) (*metav1beta1.Table, error) { + t := reflect.TypeOf(obj) + handler, ok := h.handlerMap[t] + if !ok { + return nil, fmt.Errorf("no table handler registered for this type %v", t) + } + + args := []reflect.Value{reflect.ValueOf(obj), reflect.ValueOf(options)} + results := handler.printFunc.Call(args) + if !results[1].IsNil() { + return nil, results[1].Interface().(error) + } + + columns := make([]metav1beta1.TableColumnDefinition, 0, len(handler.columnDefinitions)) + for i := range handler.columnDefinitions { + columns = append(columns, handler.columnDefinitions[i]) + } + + table := &metav1beta1.Table{ + ListMeta: metav1.ListMeta{ + ResourceVersion: "", + }, + ColumnDefinitions: columns, + Rows: results[0].Interface().([]metav1beta1.TableRow), + } + if m, err := meta.ListAccessor(obj); err == nil { + table.ResourceVersion = m.GetResourceVersion() + table.Continue = m.GetContinue() + } else { + if m, err := meta.CommonAccessor(obj); err == nil { + table.ResourceVersion = m.GetResourceVersion() + } + } + return table, nil +} + +// TableHandler adds a print handler with a given set of columns to HumanReadablePrinter instance. +// See ValidateRowPrintHandlerFunc for required method signature. +func (h *HumanReadablePrinter) TableHandler(columnDefinitions []metav1beta1.TableColumnDefinition, printFunc interface{}) error { + printFuncValue := reflect.ValueOf(printFunc) + if err := ValidateRowPrintHandlerFunc(printFuncValue); err != nil { + utilruntime.HandleError(fmt.Errorf("unable to register print function: %w", err)) + return err + } + entry := &handlerEntry{ + columnDefinitions: columnDefinitions, + printFunc: printFuncValue, + } + + objType := printFuncValue.Type().In(0) + if _, ok := h.handlerMap[objType]; ok { + err := fmt.Errorf("registered duplicate printer for %v", objType) + utilruntime.HandleError(err) + return err + } + h.handlerMap[objType] = entry + return nil +} + +// ValidateRowPrintHandlerFunc validates print handler signature. +// printFunc is the function that will be called to print an object. +// It must be of the following type: +// +// func printFunc(object ObjectType, options PrintOptions) ([]metav1beta1.TableRow, error) +// +// where ObjectType is the type of the object that will be printed, and the first +// return value is an array of rows, with each row containing a number of cells that +// match the number of columns defined for that printer function. +func ValidateRowPrintHandlerFunc(printFunc reflect.Value) error { + if printFunc.Kind() != reflect.Func { + return fmt.Errorf("invalid print handler. %#v is not a function", printFunc) + } + funcType := printFunc.Type() + if funcType.NumIn() != 2 || funcType.NumOut() != 2 { + return fmt.Errorf("invalid print handler." + + "Must accept 2 parameters and return 2 value.") + } + if funcType.In(1) != reflect.TypeOf((*PrintOptions)(nil)).Elem() || + funcType.Out(0) != reflect.TypeOf((*[]metav1beta1.TableRow)(nil)).Elem() || + funcType.Out(1) != reflect.TypeOf((*error)(nil)).Elem() { + return fmt.Errorf("invalid print handler. The expected signature is: "+ + "func handler(obj %v, options PrintOptions) ([]metav1beta1.TableRow, error)", funcType.In(0)) + } + return nil +} diff --git a/vendor/knative.dev/client-pkg/pkg/printers/tableprinter.go b/vendor/knative.dev/client-pkg/pkg/printers/tableprinter.go new file mode 100644 index 0000000000..ae7a020394 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/printers/tableprinter.go @@ -0,0 +1,117 @@ +/* +Copyright 2019 The Kubernetes 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. +*/ + +// The following is a subset of original implementation +// at https://github.com/kubernetes/kubernetes/blob/v1.15.0-alpha.2/pkg/printers/tableprinter.go + +package printers + +import ( + "fmt" + "io" + "reflect" + "strings" + + "text/tabwriter" + + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" + "k8s.io/apimachinery/pkg/runtime" +) + +var _ ResourcePrinter = &HumanReadablePrinter{} + +// NewTablePrinter creates a printer suitable for calling PrintObj(). +func NewTablePrinter(options PrintOptions) *HumanReadablePrinter { + printer := &HumanReadablePrinter{ + handlerMap: make(map[reflect.Type]*handlerEntry), + options: options, + } + return printer +} + +// PrintObj prints the obj in a human-friendly format according to the type of the obj. +func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) error { + if obj == nil { + return nil + } + + if _, found := output.(*tabwriter.Writer); !found { + w := NewTabWriter(output) + output = w + defer w.Flush() + } + + // Search for a handler registered handler to print it + t := reflect.TypeOf(obj) + if handler := h.handlerMap[t]; handler != nil { + + if err := printRowsForHandlerEntry(output, handler, obj, h.options); err != nil { + return err + } + return nil + } + + // we failed all reasonable printing efforts, report failure + return fmt.Errorf("error: unknown type %#v", obj) +} + +// printRowsForHandlerEntry prints the incremental table output +// including all the rows in the object. It returns the current type +// or an error, if any. +func printRowsForHandlerEntry(output io.Writer, handler *handlerEntry, obj runtime.Object, options PrintOptions) error { + var results []reflect.Value + + args := []reflect.Value{reflect.ValueOf(obj), reflect.ValueOf(options)} + results = handler.printFunc.Call(args) + if !results[1].IsNil() { + return results[1].Interface().(error) + } + + if !options.NoHeaders { + var headers []string + for _, column := range handler.columnDefinitions { + if !options.AllNamespaces && column.Priority == 0 { + continue + } + headers = append(headers, strings.ToUpper(column.Name)) + } + printHeader(headers, output) + } + + if results[1].IsNil() { + rows := results[0].Interface().([]metav1beta1.TableRow) + printRows(output, rows) + return nil + } + return results[1].Interface().(error) +} + +func printHeader(columnNames []string, w io.Writer) error { + if _, err := fmt.Fprintf(w, "%s\n", strings.Join(columnNames, "\t")); err != nil { + return err + } + return nil +} + +// printRows writes the provided rows to output. +func printRows(output io.Writer, rows []metav1beta1.TableRow) { + for _, row := range rows { + for i, cell := range row.Cells { + if i != 0 { + fmt.Fprint(output, "\t") + } + fmt.Fprint(output, cell) + } + output.Write([]byte("\n")) + } +} diff --git a/vendor/knative.dev/client-pkg/pkg/printers/tabwriter.go b/vendor/knative.dev/client-pkg/pkg/printers/tabwriter.go new file mode 100644 index 0000000000..c29efe4837 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/printers/tabwriter.go @@ -0,0 +1,36 @@ +/* +Copyright 2017 The Kubernetes 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. +*/ + +// The following is a subset of original implementation +// at https://github.com/kubernetes/kubernetes/blob/v1.15.0-alpha.2/pkg/printers/tabwriter.go + +package printers + +import ( + "io" + + "text/tabwriter" +) + +const ( + tabwriterMinWidth = 6 + tabwriterWidth = 4 + tabwriterPadding = 3 + tabwriterPadChar = ' ' + tabwriterFlags = tabwriter.TabIndent +) + +// NewTabWriter returns a tabwriter that translates tabbed columns in input into properly aligned text. +func NewTabWriter(output io.Writer) *tabwriter.Writer { + return tabwriter.NewWriter(output, tabwriterMinWidth, tabwriterWidth, tabwriterPadding, tabwriterPadChar, tabwriterFlags) +} diff --git a/vendor/knative.dev/client-pkg/pkg/serving/config_changes.go b/vendor/knative.dev/client-pkg/pkg/serving/config_changes.go new file mode 100644 index 0000000000..4a7f153288 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/serving/config_changes.go @@ -0,0 +1,240 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package serving + +import ( + "context" + "errors" + "fmt" + "strconv" + "strings" + "time" + + "knative.dev/client-pkg/pkg/kn/flags" + "knative.dev/pkg/ptr" + "knative.dev/serving/pkg/apis/autoscaling" + servingconfig "knative.dev/serving/pkg/apis/config" + servingv1 "knative.dev/serving/pkg/apis/serving/v1" +) + +// VolumeSourceType is a type standing for enumeration of ConfigMap and Secret +type VolumeSourceType int + +// Enumeration of volume source types: ConfigMap or Secret +const ( + ConfigMapVolumeSourceType VolumeSourceType = iota + SecretVolumeSourceType + PortFormatErr = "the port specification '%s' is not valid. Please provide in the format 'NAME:PORT', where 'NAME' is optional. Examples: '--port h2c:8080' , '--port 8080'." +) + +var ( + UserImageAnnotationKey = "client.knative.dev/user-image" + UpdateTimestampAnnotationKey = "client.knative.dev/updateTimestamp" + APITooOldError = errors.New("the service is using too old of an API format for the operation") +) + +func (vt VolumeSourceType) String() string { + names := [...]string{"config-map", "secret"} + if vt < ConfigMapVolumeSourceType || vt > SecretVolumeSourceType { + return "unknown" + } + return names[vt] +} + +// UpdateMinScale updates min scale annotation +func UpdateMinScale(template *servingv1.RevisionTemplateSpec, min int) error { + return UpdateRevisionTemplateAnnotation(template, autoscaling.MinScaleAnnotationKey, strconv.Itoa(min)) +} + +// UpdateMaxScale updates max scale annotation +func UpdateMaxScale(template *servingv1.RevisionTemplateSpec, max int) error { + return UpdateRevisionTemplateAnnotation(template, autoscaling.MaxScaleAnnotationKey, strconv.Itoa(max)) +} + +// UpdateScaleWindow updates the autoscale window annotation +func UpdateScaleWindow(template *servingv1.RevisionTemplateSpec, window string) error { + _, err := time.ParseDuration(window) + if err != nil { + return fmt.Errorf("invalid duration for 'scale-window': %w", err) + } + return UpdateRevisionTemplateAnnotation(template, autoscaling.WindowAnnotationKey, window) +} + +// UpdateScaleTarget updates container concurrency annotation +func UpdateScaleTarget(template *servingv1.RevisionTemplateSpec, target int) error { + return UpdateRevisionTemplateAnnotation(template, autoscaling.TargetAnnotationKey, strconv.Itoa(target)) +} + +// UpdateScaleActivation updates the scale activation annotation +func UpdateScaleActivation(template *servingv1.RevisionTemplateSpec, activation int) error { + return UpdateRevisionTemplateAnnotation(template, autoscaling.ActivationScaleKey, strconv.Itoa(activation)) +} + +// UpdateScaleUtilization updates container target utilization percentage annotation +func UpdateScaleUtilization(template *servingv1.RevisionTemplateSpec, target int) error { + return UpdateRevisionTemplateAnnotation(template, autoscaling.TargetUtilizationPercentageKey, strconv.Itoa(target)) +} + +// UpdateConcurrencyLimit updates container concurrency limit +func UpdateConcurrencyLimit(template *servingv1.RevisionTemplateSpec, limit int64) error { + if limit < 0 { + return fmt.Errorf("invalid concurrency-limit %d (must not be less than 0)", limit) + } + template.Spec.ContainerConcurrency = ptr.Int64(limit) + return nil +} + +// UnsetUserImageAnnotation removes the user image annotation +func UnsetUserImageAnnotation(template *servingv1.RevisionTemplateSpec) { + delete(template.Annotations, UserImageAnnotationKey) +} + +// UpdateUserImageAnnotation sets the user image annotation if the image isn't by-digest already. +func UpdateUserImageAnnotation(template *servingv1.RevisionTemplateSpec) { + // If the current image isn't by-digest, set the user-image annotation to it + // so we remember what it was. + currentContainer := ContainerOfRevisionSpec(&template.Spec) + if currentContainer == nil { + // No container set in the template, so + return + } + image := currentContainer.Image + if strings.Contains(image, "@") { + // Ensure that the non-digestified image is used + storedImage, ok := template.Annotations[UserImageAnnotationKey] + if ok { + image = storedImage + } + } + ensureAnnotations(template) + template.Annotations[UserImageAnnotationKey] = image +} + +// UpdateTimestampAnnotation update the annotation for the last update with the current timestamp +func UpdateTimestampAnnotation(template *servingv1.RevisionTemplateSpec) { + ensureAnnotations(template) + + template.Annotations[UpdateTimestampAnnotationKey] = time.Now().UTC().Format(time.RFC3339) +} + +func ensureAnnotations(template *servingv1.RevisionTemplateSpec) { + if template.Annotations == nil { + template.Annotations = make(map[string]string) + } +} + +// PinImageToDigest sets the image on the template to the image digest of the base revision. +func PinImageToDigest(currentRevisionTemplate *servingv1.RevisionTemplateSpec, baseRevision *servingv1.Revision) error { + // If there is no base revision then there is nothing to pin to. It's not an error so let's return + // silently + if baseRevision == nil { + return nil + } + + err := VerifyThatContainersMatchInCurrentAndBaseRevision(currentRevisionTemplate, baseRevision) + if err != nil { + return fmt.Errorf("can not pin image to digest: %w", err) + } + + containerStatus := ContainerStatus(baseRevision) + if containerStatus != nil && containerStatus.ImageDigest != "" { + return flags.UpdateImage(¤tRevisionTemplate.Spec.PodSpec, containerStatus.ImageDigest) + } + return nil +} + +// VerifyThatContainersMatchInCurrentAndBaseRevision checks if the image in the current revision matches +// matches the one in a given base revision +func VerifyThatContainersMatchInCurrentAndBaseRevision(template *servingv1.RevisionTemplateSpec, baseRevision *servingv1.Revision) error { + currentContainer := ContainerOfRevisionSpec(&template.Spec) + if currentContainer == nil { + return fmt.Errorf("no container given in current revision %s", template.Name) + } + + baseContainer := ContainerOfRevisionSpec(&baseRevision.Spec) + if baseContainer == nil { + return fmt.Errorf("no container found in base revision %s", baseRevision.Name) + } + + if currentContainer.Image != baseContainer.Image { + return fmt.Errorf("current revision %s contains unexpected image (%s) that does not fit to the base revision's %s image (%s)", template.Name, currentContainer.Image, baseRevision.Name, baseContainer.Image) + } + return nil +} + +// UpdateLabels updates the labels by adding items from `add` then removing any items from `remove` +func UpdateLabels(labelsMap map[string]string, add map[string]string, remove []string) map[string]string { + if labelsMap == nil { + labelsMap = map[string]string{} + } + + for key, value := range add { + labelsMap[key] = value + } + for _, key := range remove { + delete(labelsMap, key) + } + + return labelsMap +} + +// UpdateServiceAnnotations updates annotations for the given Service Metadata. +func UpdateServiceAnnotations(service *servingv1.Service, toUpdate map[string]string, toRemove []string) error { + if service.Annotations == nil && len(toUpdate) > 0 { + service.Annotations = make(map[string]string) + } + return updateAnnotations(service.Annotations, toUpdate, toRemove) +} + +// UpdateRevisionTemplateAnnotations updates annotations for the given Revision Template. +// Also validates the autoscaling annotation values +func UpdateRevisionTemplateAnnotations(template *servingv1.RevisionTemplateSpec, toUpdate map[string]string, toRemove []string) error { + ctx := context.TODO() + autoscalerConfig := servingconfig.FromContextOrDefaults(ctx).Autoscaler + autoscalerConfig.AllowZeroInitialScale = true + if err := autoscaling.ValidateAnnotations(ctx, autoscalerConfig, toUpdate); err != nil { + return err + } + if template.Annotations == nil { + template.Annotations = make(map[string]string) + } + return updateAnnotations(template.Annotations, toUpdate, toRemove) +} + +// UpdateRevisionTemplateAnnotation updates an annotation for the given Revision Template. +// Also validates the autoscaling annotation values +func UpdateRevisionTemplateAnnotation(template *servingv1.RevisionTemplateSpec, annotation string, value string) error { + return UpdateRevisionTemplateAnnotations(template, map[string]string{annotation: value}, []string{}) +} + +// UpdateScaleMetric updates the metric annotation for the given Revision Template +func UpdateScaleMetric(template *servingv1.RevisionTemplateSpec, metric string) { + if template.Annotations == nil { + template.Annotations = make(map[string]string) + } + template.Annotations[autoscaling.MetricAnnotationKey] = metric +} + +// ======================================================================================= + +func updateAnnotations(annotations map[string]string, toUpdate map[string]string, toRemove []string) error { + for key, value := range toUpdate { + annotations[key] = value + } + for _, key := range toRemove { + delete(annotations, key) + } + return nil +} diff --git a/vendor/knative.dev/client-pkg/pkg/serving/revision_template.go b/vendor/knative.dev/client-pkg/pkg/serving/revision_template.go new file mode 100644 index 0000000000..efb6907aa9 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/serving/revision_template.go @@ -0,0 +1,130 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package serving + +import ( + "strconv" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/serving/pkg/apis/autoscaling" + servingv1 "knative.dev/serving/pkg/apis/serving/v1" +) + +type Scaling struct { + Min *int + Max *int +} + +// ContainerOfRevisionSpec returns the 'main' container of a revision specification and +// use GetServingContainerIndex to identify the container. +// Nil is returned if no such container could be found +func ContainerOfRevisionSpec(revisionSpec *servingv1.RevisionSpec) *corev1.Container { + idx := ContainerIndexOfRevisionSpec(revisionSpec) + if idx == -1 { + return nil + } + return &revisionSpec.Containers[0] +} + +// ContainerIndexOfRevisionSpec returns the index of the "main" container if +// multiple containers are present. The main container is either the single +// container when there is only ony container in the list or the first container +// which has a ports declaration (validation guarantees that there is only one +// such container) +// If no container could be found (list is empty or no container has a port declaration) +// then -1 is returned +// This method's logic is taken from RevisionSpec.GetContainer() +func ContainerIndexOfRevisionSpec(revisionSpec *servingv1.RevisionSpec) int { + switch { + case len(revisionSpec.Containers) == 1: + return 0 + case len(revisionSpec.Containers) > 1: + for i := range revisionSpec.Containers { + if len(revisionSpec.Containers[i].Ports) != 0 { + return i + } + } + } + return -1 +} + +// ContainerStatus returns the status of the main container or nil of no +// such status could be found +func ContainerStatus(r *servingv1.Revision) *servingv1.ContainerStatus { + idx := ContainerIndexOfRevisionSpec(&r.Spec) + if idx < 0 || idx >= len(r.Status.ContainerStatuses) { + return nil + } + return &r.Status.ContainerStatuses[idx] +} + +func ScalingInfo(m *metav1.ObjectMeta) (*Scaling, error) { + ret := &Scaling{} + var err error + ret.Min, err = annotationAsInt(m, autoscaling.MinScaleAnnotationKey) + if err != nil { + return nil, err + } + ret.Max, err = annotationAsInt(m, autoscaling.MaxScaleAnnotationKey) + if err != nil { + return nil, err + } + return ret, nil +} + +func UserImage(m *metav1.ObjectMeta) string { + return m.Annotations[UserImageAnnotationKey] +} + +func ConcurrencyTarget(m *metav1.ObjectMeta) *int { + ret, _ := annotationAsInt(m, autoscaling.TargetAnnotationKey) + return ret +} + +func ConcurrencyTargetUtilization(m *metav1.ObjectMeta) *int { + ret, _ := annotationAsInt(m, autoscaling.TargetUtilizationPercentageKey) + return ret +} + +func AutoscaleWindow(m *metav1.ObjectMeta) string { + return m.Annotations[autoscaling.WindowAnnotationKey] +} + +func Port(revisionSpec *servingv1.RevisionSpec) *int32 { + c := ContainerOfRevisionSpec(revisionSpec) + if c == nil { + return nil + } + if len(c.Ports) > 0 { + p := c.Ports[0].ContainerPort + return &p + } + return nil +} + +// ======================================================================================= + +func annotationAsInt(m *metav1.ObjectMeta, annotationKey string) (*int, error) { + annos := m.Annotations + if val, ok := annos[annotationKey]; ok { + valInt, err := strconv.Atoi(val) + if err != nil { + return nil, err + } + return &valInt, nil + } + return nil, nil +} diff --git a/vendor/knative.dev/client-pkg/pkg/serving/v1/apply.go b/vendor/knative.dev/client-pkg/pkg/serving/v1/apply.go new file mode 100644 index 0000000000..40588d69f4 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/serving/v1/apply.go @@ -0,0 +1,268 @@ +package v1 + +import ( + "context" + "strings" + "time" + + v1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/jsonmergepatch" + servingv1 "knative.dev/serving/pkg/apis/serving/v1" + + "knative.dev/client-pkg/pkg/util" +) + +// 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. + +// Helper methods supporting Apply() + +// patch performs a 3-way merge and returns whether the original service has been changed +// This method uses a simple JSON 3-way merge which has some severe limitations, like that arrays +// can't be merged. Ideally a strategicpatch merge should be used, which allows a more fine grained +// way for performing the merge (but this is not supported for custom resources) +// See issue https://github.com/knative/client/issues/1073 for more details how this method should be +// improved for a better merge strategy. +func (cl *knServingClient) patch(ctx context.Context, modifiedService *servingv1.Service, currentService *servingv1.Service, uOriginalService []byte) (bool, error) { + uModifiedService, err := getModifiedConfiguration(modifiedService, true) + if err != nil { + return false, err + } + hasChanged, err := cl.patchSimple(ctx, currentService, uModifiedService, uOriginalService) + for i := 1; i <= 5 && apierrors.IsConflict(err); i++ { + if i > 1 { + time.Sleep(1 * time.Second) + } + currentService, err = cl.GetService(ctx, currentService.Name) + if err != nil { + return false, err + } + hasChanged, err = cl.patchSimple(ctx, currentService, uModifiedService, uOriginalService) + } + return hasChanged, err +} + +func (cl *knServingClient) patchSimple(ctx context.Context, currentService *servingv1.Service, uModifiedService []byte, uOriginalService []byte) (bool, error) { + // Serialize the current configuration of the object from the server. + uCurrentService, err := encodeService(currentService) + if err != nil { + return false, err + } + + patch, err := jsonmergepatch.CreateThreeWayJSONMergePatch(uOriginalService, uModifiedService, uCurrentService) + if err != nil { + return false, err + } + + if string(patch) == "{}" { + return false, nil + } + + // Check if the generation has been counted up, only then the backend detected a change + savedService, err := cl.patchService(ctx, currentService.Name, types.MergePatchType, patch) + if err != nil { + return false, err + } + return savedService.Generation != savedService.Status.ObservedGeneration, nil +} + +// patchService patches the given service +func (cl *knServingClient) patchService(ctx context.Context, name string, patchType types.PatchType, patch []byte) (*servingv1.Service, error) { + service, err := cl.client.Services(cl.namespace).Patch(ctx, name, patchType, patch, metav1.PatchOptions{}) + if err != nil { + return nil, err + } + err = updateServingGvk(service) + + return service, err +} + +func getOriginalConfiguration(service *servingv1.Service) []byte { + annots := service.Annotations + if annots == nil { + return nil + } + original, ok := annots[v1.LastAppliedConfigAnnotation] + if !ok { + return nil + } + return []byte(original) +} + +func getModifiedConfiguration(service *servingv1.Service, annotate bool) ([]byte, error) { + + // First serialize the object without the annotation to prevent recursion, + // then add that serialization to it as the annotation and serialize it again. + var uModifiedService []byte + + // Otherwise, use the server side version of the object. + // Get the current annotations from the object. + annots := service.Annotations + if annots == nil { + annots = map[string]string{} + } + + original := annots[v1.LastAppliedConfigAnnotation] + delete(annots, v1.LastAppliedConfigAnnotation) + service.Annotations = annots + + uModifiedService, err := encodeService(service) + if err != nil { + return nil, err + } + + if annotate { + annots[v1.LastAppliedConfigAnnotation] = strings.TrimRight(string(uModifiedService), "\n") + + service.Annotations = annots + uModifiedService, err = encodeService(service) + if err != nil { + return nil, err + } + } + + // Restore the object to its original condition. + annots[v1.LastAppliedConfigAnnotation] = original + service.Annotations = annots + return uModifiedService, nil +} + +func updateLastAppliedAnnotation(service *servingv1.Service) error { + annots := service.Annotations + if annots == nil { + annots = map[string]string{} + } + lastApplied, err := encodeService(service) + if err != nil { + return err + } + + // Cleanup any trailing newlines + annots[v1.LastAppliedConfigAnnotation] = strings.TrimRight(string(lastApplied), "\n") + + service.Annotations = annots + return nil +} + +func encodeService(service *servingv1.Service) ([]byte, error) { + scheme := runtime.NewScheme() + err := servingv1.AddToScheme(scheme) + if err != nil { + return nil, err + } + factory := serializer.NewCodecFactory(scheme) + encoder := factory.EncoderForVersion(unstructured.UnstructuredJSONScheme, servingv1.SchemeGroupVersion) + err = util.UpdateGroupVersionKindWithScheme(service, servingv1.SchemeGroupVersion, scheme) + if err != nil { + return nil, err + } + + serviceUnstructured, err := util.ToUnstructured(service) + if err != nil { + return nil, err + } + + // Remove/adapt service so that it can be used in the apply-annotation + cleanupServiceUnstructured(serviceUnstructured) + + return runtime.Encode(encoder, serviceUnstructured) +} + +func cleanupServiceUnstructured(uService *unstructured.Unstructured) { + clearCreationTimestamps(uService.Object) + removeStatus(uService.Object) + removeContainerNameAndResourcesIfNotSet(uService.Object) + +} + +func removeContainerNameAndResourcesIfNotSet(uService map[string]interface{}) { + uContainer := extractUserContainer(uService) + if uContainer == nil { + return + } + name, ok := uContainer["name"] + if ok && name != "" { + delete(uContainer, "name") + } + + resources := uContainer["resources"] + if resources == nil { + return + } + resourcesMap := resources.(map[string]interface{}) + if len(resourcesMap) == 0 { + delete(uContainer, "resources") + } +} + +func extractUserContainer(uService map[string]interface{}) map[string]interface{} { + tSpec := extractTemplateSpec(uService) + if tSpec == nil { + return nil + } + containers := tSpec["containers"] + if len(containers.([]interface{})) == 0 { + return nil + } + return containers.([]interface{})[0].(map[string]interface{}) +} + +func removeStatus(uService map[string]interface{}) { + delete(uService, "status") +} + +func clearCreationTimestamps(uService map[string]interface{}) { + meta := uService["metadata"] + if meta != nil { + delete(meta.(map[string]interface{}), "creationTimestamp") + } + template := extractTemplate(uService) + if template != nil { + meta = template["metadata"] + if meta != nil { + delete(meta.(map[string]interface{}), "creationTimestamp") + } + } +} + +func extractTemplateSpec(uService map[string]interface{}) map[string]interface{} { + templ := extractTemplate(uService) + if templ == nil { + return nil + } + templSpec := templ["spec"] + if templSpec == nil { + return nil + } + + return templSpec.(map[string]interface{}) +} + +func extractTemplate(uService map[string]interface{}) map[string]interface{} { + spec := uService["spec"] + if spec == nil { + return nil + } + templ := spec.(map[string]interface{})["template"] + if templ == nil { + return nil + } + return templ.(map[string]interface{}) +} diff --git a/vendor/knative.dev/client-pkg/pkg/serving/v1/client.go b/vendor/knative.dev/client-pkg/pkg/serving/v1/client.go new file mode 100644 index 0000000000..9c83ab5959 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/serving/v1/client.go @@ -0,0 +1,581 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + "context" + "errors" + "fmt" + "time" + + "knative.dev/client-pkg/pkg/config" + + "k8s.io/client-go/util/retry" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/fields" + "knative.dev/pkg/apis" + "knative.dev/serving/pkg/client/clientset/versioned/scheme" + + "knative.dev/client-pkg/pkg/serving" + "knative.dev/client-pkg/pkg/util" + "knative.dev/client-pkg/pkg/wait" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + apiserving "knative.dev/serving/pkg/apis/serving" + servingv1 "knative.dev/serving/pkg/apis/serving/v1" + clientv1 "knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1" + + clienterrors "knative.dev/client-pkg/pkg/errors" +) + +// Func signature for an updating function which returns the updated service object +// or an error +type ServiceUpdateFunc func(origService *servingv1.Service) (*servingv1.Service, error) + +type WaitConfig struct { + Timeout time.Duration + ErrorWindow time.Duration +} + +// Kn interface to serving. All methods are relative to the +// namespace specified during construction +type KnServingClient interface { + + // Namespace in which this client is operating for + Namespace() string + + // Get a service by its unique name + GetService(ctx context.Context, name string) (*servingv1.Service, error) + + // List services + ListServices(ctx context.Context, opts ...ListConfig) (*servingv1.ServiceList, error) + + // Create a new service + CreateService(ctx context.Context, service *servingv1.Service) error + + // UpdateService updates the given service. For a more robust variant with automatic + // conflict resolution see UpdateServiceWithRetry + UpdateService(ctx context.Context, service *servingv1.Service) (bool, error) + + // UpdateServiceWithRetry updates service and retries if there is a version conflict. + // The updateFunc receives a deep copy of the existing service and can add update it in + // place. Return if the service creates a new generation or not + UpdateServiceWithRetry(ctx context.Context, name string, updateFunc ServiceUpdateFunc, nrRetries int) (bool, error) + + // Apply a service's definition to the cluster. The full service declaration needs to be provided, + // which is different to UpdateService which can also do a partial update. If the given + // service does not already exists (identified by name) then the service is create. + // If the service exists, then a three-way merge will be performed between the original + // configuration given (from the last "apply" operation), the new configuration as given ] + // here and the current configuration as found on the cluster. + // The returned bool indicates whether the service has been changed or whether this operation + // was a no-op + // An error can indicate a general error or a conflict that occurred during the three way merge. + ApplyService(ctx context.Context, service *servingv1.Service) (bool, error) + + // Delete a service by name + DeleteService(ctx context.Context, name string, timeout time.Duration) error + + // Wait for a service to become ready, but not longer than provided timeout. + // Return error and how long has been waited + WaitForService(ctx context.Context, name string, wconfig WaitConfig, msgCallback wait.MessageCallback) (error, time.Duration) + + // Get a configuration by name + GetConfiguration(ctx context.Context, name string) (*servingv1.Configuration, error) + + // Get a revision by name + GetRevision(ctx context.Context, name string) (*servingv1.Revision, error) + + // Get the "base" revision for a Service; the one that corresponds to the + // current template. + GetBaseRevision(ctx context.Context, service *servingv1.Service) (*servingv1.Revision, error) + + // Create revision + CreateRevision(ctx context.Context, revision *servingv1.Revision) error + + // Update revision + UpdateRevision(ctx context.Context, revision *servingv1.Revision) error + + // List revisions + ListRevisions(ctx context.Context, opts ...ListConfig) (*servingv1.RevisionList, error) + + // Delete a revision + DeleteRevision(ctx context.Context, name string, timeout time.Duration) error + + // Get a route by its unique name + GetRoute(ctx context.Context, name string) (*servingv1.Route, error) + + // List routes + ListRoutes(ctx context.Context, opts ...ListConfig) (*servingv1.RouteList, error) +} + +type listConfigCollector struct { + // Labels to filter on + Labels labels.Set + + // Labels to filter on + Fields fields.Set +} + +// Config function for builder pattern +type ListConfig func(config *listConfigCollector) + +type ListConfigs []ListConfig + +// add selectors to a list options +func (opts ListConfigs) toListOptions() v1.ListOptions { + listConfig := listConfigCollector{labels.Set{}, fields.Set{}} + for _, f := range opts { + f(&listConfig) + } + options := v1.ListOptions{} + if len(listConfig.Fields) > 0 { + options.FieldSelector = listConfig.Fields.String() + } + if len(listConfig.Labels) > 0 { + options.LabelSelector = listConfig.Labels.String() + } + return options +} + +// Filter list on the provided name +func WithName(name string) ListConfig { + return func(lo *listConfigCollector) { + lo.Fields["metadata.name"] = name + } +} + +// Filter on the service name +func WithService(service string) ListConfig { + return func(lo *listConfigCollector) { + lo.Labels[apiserving.ServiceLabelKey] = service + } +} + +// WithLabel filters on the provided label +func WithLabel(labelKey, labelValue string) ListConfig { + return func(lo *listConfigCollector) { + lo.Labels[labelKey] = labelValue + } +} + +type knServingClient struct { + client clientv1.ServingV1Interface + namespace string +} + +// Create a new client facade for the provided namespace +func NewKnServingClient(client clientv1.ServingV1Interface, namespace string) KnServingClient { + return &knServingClient{ + client: client, + namespace: namespace, + } +} + +// Return the client's namespace +func (cl *knServingClient) Namespace() string { + return cl.namespace +} + +// Get a service by its unique name +func (cl *knServingClient) GetService(ctx context.Context, name string) (*servingv1.Service, error) { + service, err := cl.client.Services(cl.namespace).Get(ctx, name, v1.GetOptions{}) + if err != nil { + return nil, clienterrors.GetError(err) + } + err = updateServingGvk(service) + if err != nil { + return nil, err + } + return service, nil +} + +func (cl *knServingClient) WatchServiceWithVersion(ctx context.Context, name string, initialVersion string, timeout time.Duration) (watch.Interface, error) { + return wait.NewWatcherWithVersion(ctx, cl.client.Services(cl.namespace).Watch, cl.client.RESTClient(), cl.namespace, "services", name, initialVersion, timeout) +} + +func (cl *knServingClient) WatchRevisionWithVersion(ctx context.Context, name string, initialVersion string, timeout time.Duration) (watch.Interface, error) { + return wait.NewWatcherWithVersion(ctx, cl.client.Revisions(cl.namespace).Watch, cl.client.RESTClient(), cl.namespace, "revision", name, initialVersion, timeout) +} + +// List services +func (cl *knServingClient) ListServices(ctx context.Context, config ...ListConfig) (*servingv1.ServiceList, error) { + serviceList, err := cl.client.Services(cl.namespace).List(ctx, ListConfigs(config).toListOptions()) + if err != nil { + return nil, clienterrors.GetError(err) + } + serviceListNew := serviceList.DeepCopy() + err = updateServingGvk(serviceListNew) + if err != nil { + return nil, err + } + + serviceListNew.Items = make([]servingv1.Service, len(serviceList.Items)) + for idx, service := range serviceList.Items { + serviceClone := service.DeepCopy() + err := updateServingGvk(serviceClone) + if err != nil { + return nil, err + } + serviceListNew.Items[idx] = *serviceClone + } + return serviceListNew, nil +} + +// Create a new service +func (cl *knServingClient) CreateService(ctx context.Context, service *servingv1.Service) error { + _, err := cl.client.Services(cl.namespace).Create(ctx, service, v1.CreateOptions{}) + if err != nil { + return clienterrors.GetError(err) + } + return updateServingGvk(service) +} + +// Update the given service +func (cl *knServingClient) UpdateService(ctx context.Context, service *servingv1.Service) (bool, error) { + updated, err := cl.client.Services(cl.namespace).Update(ctx, service, v1.UpdateOptions{}) + if err != nil { + return false, err + } + changed := service.ObjectMeta.Generation != updated.ObjectMeta.Generation + return changed, updateServingGvk(service) +} + +// Update the given service with a retry in case of a conflict +func (cl *knServingClient) UpdateServiceWithRetry(ctx context.Context, name string, updateFunc ServiceUpdateFunc, nrRetries int) (bool, error) { + return updateServiceWithRetry(ctx, cl, name, updateFunc, nrRetries) +} + +// Extracted to be usable with the Mocking client +func updateServiceWithRetry(ctx context.Context, cl KnServingClient, name string, updateFunc ServiceUpdateFunc, nrRetries int) (bool, error) { + var changed bool + var err error + b := config.DefaultRetry + b.Steps = nrRetries + err = retry.RetryOnConflict(b, func() error { + service, err := cl.GetService(ctx, name) + if err != nil { + return err + } + if service.GetDeletionTimestamp() != nil { + return fmt.Errorf("can't update service %s because it has been marked for deletion", name) + } + updatedService, err := updateFunc(service.DeepCopy()) + if err != nil { + return err + } + + changed, err = cl.UpdateService(ctx, updatedService) + return err + }) + return changed, err +} + +// ApplyService applies a service definition that contains the service's targer state +func (cl *knServingClient) ApplyService(ctx context.Context, modifiedService *servingv1.Service) (bool, error) { + currentService, err := cl.GetService(ctx, modifiedService.Name) + if err != nil && !apierrors.IsNotFound(err) { + return false, err + } + + containers := modifiedService.Spec.Template.Spec.Containers + if len(containers) == 0 || containers[0].Image == "" && currentService != nil { + return false, errors.New("'service apply' requires the image name to run provided with the --image option") + } + + // No current service --> create a new service + if currentService == nil { + err := updateLastAppliedAnnotation(modifiedService) + if err != nil { + return false, err + } + return true, cl.CreateService(ctx, modifiedService) + } + + // Merge with existing service + uOriginalService := getOriginalConfiguration(currentService) + return cl.patch(ctx, modifiedService, currentService, uOriginalService) +} + +// Delete a service by name +// Param `timeout` represents a duration to wait for a delete op to finish. +// For `timeout == 0` delete is performed async without any wait. +func (cl *knServingClient) DeleteService(ctx context.Context, serviceName string, timeout time.Duration) error { + service, err := cl.GetService(ctx, serviceName) + if err != nil { + return err + } + if service.GetDeletionTimestamp() != nil { + return fmt.Errorf("can't delete service '%s' because it has been already marked for deletion", serviceName) + } + if timeout == 0 { + return cl.deleteService(ctx, serviceName, v1.DeletePropagationBackground) + } + + waitC := make(chan error) + go func() { + waitForEvent := wait.NewWaitForEvent("service", cl.WatchServiceWithVersion, func(evt *watch.Event) bool { return evt.Type == watch.Deleted }) + err, _ := waitForEvent.Wait(ctx, serviceName, service.ResourceVersion, wait.Options{Timeout: &timeout}, wait.NoopMessageCallback()) + waitC <- err + }() + err = cl.deleteService(ctx, serviceName, v1.DeletePropagationForeground) + if err != nil { + return err + } + + return <-waitC +} + +func (cl *knServingClient) deleteService(ctx context.Context, serviceName string, propagationPolicy v1.DeletionPropagation) error { + err := cl.client.Services(cl.namespace).Delete( + ctx, + serviceName, + v1.DeleteOptions{PropagationPolicy: &propagationPolicy}, + ) + if err != nil { + return clienterrors.GetError(err) + } + + return nil +} + +// Wait for a service to become ready, but not longer than provided timeout +func (cl *knServingClient) WaitForService(ctx context.Context, name string, wconfig WaitConfig, msgCallback wait.MessageCallback) (error, time.Duration) { + waitForReady := wait.NewWaitForReady("service", cl.WatchServiceWithVersion, serviceConditionExtractor) + + service, err := cl.GetService(ctx, name) + if err != nil { + if apierrors.IsNotFound(err) { + return waitForReady.Wait(ctx, name, "", wait.Options{Timeout: &wconfig.Timeout, ErrorWindow: &wconfig.ErrorWindow}, msgCallback) + } + return err, 0 + } + return waitForReady.Wait(ctx, name, service.ResourceVersion, wait.Options{Timeout: &wconfig.Timeout, ErrorWindow: &wconfig.ErrorWindow}, msgCallback) +} + +// Get the configuration for a service +func (cl *knServingClient) GetConfiguration(ctx context.Context, name string) (*servingv1.Configuration, error) { + configuration, err := cl.client.Configurations(cl.namespace).Get(ctx, name, v1.GetOptions{}) + if err != nil { + return nil, err + } + err = updateServingGvk(configuration) + if err != nil { + return nil, err + } + return configuration, nil +} + +// Get a revision by name +func (cl *knServingClient) GetRevision(ctx context.Context, name string) (*servingv1.Revision, error) { + revision, err := cl.client.Revisions(cl.namespace).Get(ctx, name, v1.GetOptions{}) + if err != nil { + return nil, clienterrors.GetError(err) + } + err = updateServingGvk(revision) + if err != nil { + return nil, err + } + return revision, nil +} + +type NoBaseRevisionError struct { + msg string +} + +func (e NoBaseRevisionError) Error() string { + return e.msg +} + +var noBaseRevisionError = &NoBaseRevisionError{"base revision not found"} + +// Get a "base" revision. This is the revision corresponding to the template of +// a Service. It may not be findable with our heuristics, in which case this +// method returns Errors()["no-base-revision"]. If it simply doesn't exist (like +// it wasn't yet created or was deleted), return the usual not found error. +func (cl *knServingClient) GetBaseRevision(ctx context.Context, service *servingv1.Service) (*servingv1.Revision, error) { + return getBaseRevision(ctx, cl, service) +} + +func getBaseRevision(ctx context.Context, cl KnServingClient, service *servingv1.Service) (*servingv1.Revision, error) { + template := service.Spec.Template + // First, try to get it by name. If the template has a particular name, the + // base revision is the one created with that name. + if template.Name != "" { + return cl.GetRevision(ctx, template.Name) + } + // Next, let's try the LatestCreatedRevision, and see if that matches the + // template, at least in terms of the image (which is what we care about here). + if service.Status.LatestCreatedRevisionName != "" { + latestCreated, err := cl.GetRevision(ctx, service.Status.LatestCreatedRevisionName) + if err != nil { + return nil, err + } + + err = serving.VerifyThatContainersMatchInCurrentAndBaseRevision(&template, latestCreated) + if err != nil { + return nil, err + } + // There is still some chance the latestCreatedRevision is out of date, + // but we can't check the whole thing for equality because of + // server-side defaulting. Since what we probably want it for is to + // check the image digest anyway, keep it as good enough. + return latestCreated, nil + } + return nil, noBaseRevisionError +} + +// Create a revision +func (cl *knServingClient) CreateRevision(ctx context.Context, revision *servingv1.Revision) error { + rev, err := cl.client.Revisions(cl.namespace).Create(ctx, revision, v1.CreateOptions{}) + if err != nil { + return clienterrors.GetError(err) + } + return updateServingGvk(rev) +} + +// Update the given service +func (cl *knServingClient) UpdateRevision(ctx context.Context, revision *servingv1.Revision) error { + _, err := cl.client.Revisions(cl.namespace).Update(ctx, revision, v1.UpdateOptions{}) + if err != nil { + return err + } + return updateServingGvk(revision) +} + +// Delete a revision by name +func (cl *knServingClient) DeleteRevision(ctx context.Context, name string, timeout time.Duration) error { + revision, err := cl.client.Revisions(cl.namespace).Get(ctx, name, v1.GetOptions{}) + if err != nil { + return clienterrors.GetError(err) + } + if revision.GetDeletionTimestamp() != nil { + return fmt.Errorf("can't delete revision '%s' because it has been already marked for deletion", name) + } + if timeout == 0 { + return cl.deleteRevision(ctx, name) + } + waitC := make(chan error) + go func() { + waitForEvent := wait.NewWaitForEvent("revision", cl.WatchRevisionWithVersion, func(evt *watch.Event) bool { return evt.Type == watch.Deleted }) + err, _ := waitForEvent.Wait(ctx, name, revision.ResourceVersion, wait.Options{Timeout: &timeout}, wait.NoopMessageCallback()) + waitC <- err + }() + err = cl.deleteRevision(ctx, name) + if err != nil { + return clienterrors.GetError(err) + } + + return <-waitC +} + +func (cl *knServingClient) deleteRevision(ctx context.Context, name string) error { + err := cl.client.Revisions(cl.namespace).Delete(ctx, name, v1.DeleteOptions{}) + if err != nil { + return clienterrors.GetError(err) + } + + return nil +} + +// List revisions +func (cl *knServingClient) ListRevisions(ctx context.Context, config ...ListConfig) (*servingv1.RevisionList, error) { + revisionList, err := cl.client.Revisions(cl.namespace).List(ctx, ListConfigs(config).toListOptions()) + if err != nil { + return nil, clienterrors.GetError(err) + } + return updateServingGvkForRevisionList(revisionList) +} + +// Get a route by its unique name +func (cl *knServingClient) GetRoute(ctx context.Context, name string) (*servingv1.Route, error) { + route, err := cl.client.Routes(cl.namespace).Get(ctx, name, v1.GetOptions{}) + if err != nil { + return nil, err + } + err = updateServingGvk(route) + if err != nil { + return nil, err + } + return route, nil +} + +// List routes +func (cl *knServingClient) ListRoutes(ctx context.Context, config ...ListConfig) (*servingv1.RouteList, error) { + routeList, err := cl.client.Routes(cl.namespace).List(ctx, ListConfigs(config).toListOptions()) + if err != nil { + return nil, err + } + return updateServingGvkForRouteList(routeList) +} + +// update all the list + all items contained in the list with +// the proper GroupVersionKind specific to Knative serving +func updateServingGvkForRevisionList(revisionList *servingv1.RevisionList) (*servingv1.RevisionList, error) { + revisionListNew := revisionList.DeepCopy() + err := updateServingGvk(revisionListNew) + if err != nil { + return nil, err + } + + revisionListNew.Items = make([]servingv1.Revision, len(revisionList.Items)) + for idx := range revisionList.Items { + revision := revisionList.Items[idx].DeepCopy() + err := updateServingGvk(revision) + if err != nil { + return nil, err + } + revisionListNew.Items[idx] = *revision + } + return revisionListNew, nil +} + +// update all the list + all items contained in the list with +// the proper GroupVersionKind specific to Knative serving +func updateServingGvkForRouteList(routeList *servingv1.RouteList) (*servingv1.RouteList, error) { + routeListNew := routeList.DeepCopy() + err := updateServingGvk(routeListNew) + if err != nil { + return nil, err + } + + routeListNew.Items = make([]servingv1.Route, len(routeList.Items)) + for idx := range routeList.Items { + revision := routeList.Items[idx].DeepCopy() + err := updateServingGvk(revision) + if err != nil { + return nil, err + } + routeListNew.Items[idx] = *revision + } + return routeListNew, nil +} + +// update with the servingv1 group + version +func updateServingGvk(obj runtime.Object) error { + return util.UpdateGroupVersionKindWithScheme(obj, servingv1.SchemeGroupVersion, scheme.Scheme) +} + +func serviceConditionExtractor(obj runtime.Object) (apis.Conditions, error) { + service, ok := obj.(*servingv1.Service) + if !ok { + return nil, fmt.Errorf("%v is not a service", obj) + } + return apis.Conditions(service.Status.Conditions), nil +} diff --git a/vendor/knative.dev/client-pkg/pkg/serving/v1/gitops.go b/vendor/knative.dev/client-pkg/pkg/serving/v1/gitops.go new file mode 100644 index 0000000000..7dcc9ad1ea --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/serving/v1/gitops.go @@ -0,0 +1,220 @@ +// 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" + "os" + "path/filepath" + "strings" + "time" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/cli-runtime/pkg/genericclioptions" + + "knative.dev/client-pkg/pkg/wait" + servingv1 "knative.dev/serving/pkg/apis/serving/v1" +) + +const ( + ksvcKind = "ksvc" +) + +// knServingGitOpsClient - kn service client +// to work on a local repo instead of a remote cluster +type knServingGitOpsClient struct { + dir string + namespace string + fileMode bool + fileFormat string + KnServingClient +} + +// NewKnServingGitOpsClient returns an instance of the +// kn service gitops client +func NewKnServingGitOpsClient(namespace, dir string) KnServingClient { + mode, format := getFileModeAndType(dir) + return &knServingGitOpsClient{ + dir: dir, + namespace: namespace, + fileMode: mode, + fileFormat: format, + } +} + +func (cl *knServingGitOpsClient) getKsvcFilePath(name string) string { + if cl.fileMode { + return cl.dir + } + return filepath.Join(cl.dir, cl.namespace, ksvcKind, name+".yaml") +} + +func getFileModeAndType(dir string) (bool, string) { + switch { + case strings.HasSuffix(dir, ".yaml"): + return true, "yaml" + case strings.HasSuffix(dir, ".yml"): + return true, "yaml" + case strings.HasSuffix(dir, ".json"): + return true, "json" + } + return false, "yaml" +} + +// Namespace returns the namespace +func (cl *knServingGitOpsClient) Namespace() string { + return cl.namespace +} + +// GetService returns the knative service for the name +func (cl *knServingGitOpsClient) GetService(ctx context.Context, name string) (*servingv1.Service, error) { + return readServiceFromFile(cl.getKsvcFilePath(name), name) +} + +// ListServices lists the services in the path provided +func (cl *knServingGitOpsClient) ListServices(ctx context.Context, opts ...ListConfig) (*servingv1.ServiceList, error) { + svcs, err := cl.listServicesFromDirectory() + if err != nil { + return nil, err + } + typeMeta := metav1.TypeMeta{ + APIVersion: "v1", + Kind: "List", + } + serviceList := &servingv1.ServiceList{ + TypeMeta: typeMeta, + Items: svcs, + } + return serviceList, nil +} + +func (cl *knServingGitOpsClient) listServicesFromDirectory() ([]servingv1.Service, error) { + if cl.fileMode { + svc, err := readServiceFromFile(cl.dir, "") + if err != nil { + return nil, err + } + return []servingv1.Service{*svc}, nil + } + var services []servingv1.Service + root := cl.dir + if cl.namespace != "" { + root = filepath.Join(cl.dir, cl.namespace) + } + if _, err := os.Stat(root); err != nil { + return nil, err + } + if err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { + switch { + // skip if dir is not ksvc + case info.IsDir(): + return nil + + // skip non yaml files + case !strings.HasSuffix(info.Name(), ".yaml"): + return nil + + // skip non ksvc dir + case !strings.Contains(path, ksvcKind): + return filepath.SkipDir + + default: + svc, err := readServiceFromFile(path, "") + if err != nil { + return err + } + services = append(services, *svc) + return nil + } + }); err != nil { + return nil, err + } + return services, nil +} + +// CreateService saves the knative service spec in +// yaml format in the local path provided +func (cl *knServingGitOpsClient) CreateService(ctx context.Context, service *servingv1.Service) error { + updateServingGvk(service) + if cl.fileMode { + return writeFile(service, cl.dir, cl.fileFormat) + } + //check if dir exist + if _, err := os.Stat(cl.dir); os.IsNotExist(err) { + return fmt.Errorf("directory '%s' not present, please create the directory and try again", cl.dir) + } + return writeFile(service, cl.getKsvcFilePath(service.ObjectMeta.Name), cl.fileFormat) +} + +func writeFile(obj runtime.Object, fp, format string) error { + if _, err := os.Stat(fp); os.IsNotExist(err) { + os.MkdirAll(filepath.Dir(fp), 0755) + } + w, err := os.Create(fp) + if err != nil { + return err + } + yamlPrinter, err := genericclioptions.NewJSONYamlPrintFlags().ToPrinter(format) + if err != nil { + return err + } + return yamlPrinter.PrintObj(obj, w) +} + +// UpdateService updates the service in +// the local directory +func (cl *knServingGitOpsClient) UpdateService(ctx context.Context, service *servingv1.Service) (bool, error) { + // check if file exist + if _, err := cl.GetService(ctx, service.ObjectMeta.Name); err != nil { + return false, err + } + // replace file + return true, cl.CreateService(ctx, service) +} + +// UpdateServiceWithRetry updates the service in the local directory +func (cl *knServingGitOpsClient) UpdateServiceWithRetry(ctx context.Context, name string, updateFunc ServiceUpdateFunc, nrRetries int) (bool, error) { + return updateServiceWithRetry(ctx, cl, name, updateFunc, nrRetries) +} + +// DeleteService removes the file from the local file system +func (cl *knServingGitOpsClient) DeleteService(ctx context.Context, serviceName string, timeout time.Duration) error { + return os.Remove(cl.getKsvcFilePath(serviceName)) +} + +// WaitForService always returns success for this client +func (cl *knServingGitOpsClient) WaitForService(ctx context.Context, name string, wconfig WaitConfig, msgCallback wait.MessageCallback) (error, time.Duration) { + return nil, 1 * time.Second +} + +func readServiceFromFile(fileKey, name string) (*servingv1.Service, error) { + var svc servingv1.Service + file, err := os.Open(fileKey) + if err != nil { + if os.IsNotExist(err) { + return nil, apierrors.NewNotFound(servingv1.Resource("services"), name) + } + return nil, err + } + decoder := yaml.NewYAMLOrJSONDecoder(file, 512) + if err := decoder.Decode(&svc); err != nil { + return nil, err + } + return &svc, nil +} diff --git a/vendor/knative.dev/client-pkg/pkg/serving/v1alpha1/client.go b/vendor/knative.dev/client-pkg/pkg/serving/v1alpha1/client.go new file mode 100644 index 0000000000..6e748ccf4d --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/serving/v1alpha1/client.go @@ -0,0 +1,214 @@ +// Copyright © 2021 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 v1alpha1 + +import ( + "context" + "fmt" + + "knative.dev/client-pkg/pkg/config" + + "k8s.io/client-go/util/retry" + + duckv1 "knative.dev/pkg/apis/duck/v1" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + knerrors "knative.dev/client-pkg/pkg/errors" + "knative.dev/client-pkg/pkg/util" + servingv1alpha1 "knative.dev/serving/pkg/apis/serving/v1alpha1" + "knative.dev/serving/pkg/client/clientset/versioned/scheme" + clientv1alpha1 "knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1alpha1" +) + +type DomainUpdateFunc func(origDomain *servingv1alpha1.DomainMapping) (*servingv1alpha1.DomainMapping, error) + +// KnServingClient to work with Serving v1alpha1 resources +type KnServingClient interface { + // Namespace in which this client is operating for + Namespace() string + + // GetDomainMapping + GetDomainMapping(ctx context.Context, name string) (*servingv1alpha1.DomainMapping, error) + + // CreateDomainMapping + CreateDomainMapping(ctx context.Context, domainMapping *servingv1alpha1.DomainMapping) error + + // UpdateDomainMapping + UpdateDomainMapping(ctx context.Context, domainMapping *servingv1alpha1.DomainMapping) error + + // UpdateDomainMappingWithRetry + UpdateDomainMappingWithRetry(ctx context.Context, name string, updateFunc DomainUpdateFunc, nrRetries int) error + + // DeleteDomainMapping + DeleteDomainMapping(ctx context.Context, name string) error + + // ListDomainMappings + ListDomainMappings(ctx context.Context) (*servingv1alpha1.DomainMappingList, error) +} + +type knServingClient struct { + client clientv1alpha1.ServingV1alpha1Interface + namespace string +} + +// NewKnServingClient create a new client facade for the provided namespace +func NewKnServingClient(client clientv1alpha1.ServingV1alpha1Interface, namespace string) KnServingClient { + return &knServingClient{ + client: client, + namespace: namespace, + } +} + +// Namespace in which this client is operating for +func (cl *knServingClient) Namespace() string { + return cl.namespace +} + +// GetDomainMapping gets DomainMapping by name +func (cl *knServingClient) GetDomainMapping(ctx context.Context, name string) (*servingv1alpha1.DomainMapping, error) { + dm, err := cl.client.DomainMappings(cl.namespace).Get(ctx, name, v1.GetOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + err = updateServingGvk(dm) + if err != nil { + return nil, err + } + return dm, nil +} + +// CreateDomainMapping creates provided DomainMapping +func (cl *knServingClient) CreateDomainMapping(ctx context.Context, domainMapping *servingv1alpha1.DomainMapping) error { + _, err := cl.client.DomainMappings(cl.namespace).Create(ctx, domainMapping, v1.CreateOptions{}) + if err != nil { + return knerrors.GetError(err) + } + return updateServingGvk(domainMapping) +} + +// UpdateDomainMapping updates provided DomainMapping +func (cl *knServingClient) UpdateDomainMapping(ctx context.Context, domainMapping *servingv1alpha1.DomainMapping) error { + _, err := cl.client.DomainMappings(cl.namespace).Update(ctx, domainMapping, v1.UpdateOptions{}) + if err != nil { + return knerrors.GetError(err) + } + return updateServingGvk(domainMapping) +} + +func (cl *knServingClient) UpdateDomainMappingWithRetry(ctx context.Context, name string, updateFunc DomainUpdateFunc, nrRetries int) error { + return updateDomainMappingWithRetry(ctx, cl, name, updateFunc, nrRetries) +} + +func updateDomainMappingWithRetry(ctx context.Context, cl KnServingClient, name string, updateFunc DomainUpdateFunc, nrRetries int) error { + b := config.DefaultRetry + b.Steps = nrRetries + err := retry.RetryOnConflict(b, func() error { + return updateDomain(ctx, cl, name, updateFunc) + }) + return err +} + +func updateDomain(ctx context.Context, c KnServingClient, name string, updateFunc DomainUpdateFunc) error { + sub, err := c.GetDomainMapping(ctx, name) + if err != nil { + return err + } + if sub.GetDeletionTimestamp() != nil { + return fmt.Errorf("can't update domain mapping %s because it has been marked for deletion", name) + } + updatedSource, err := updateFunc(sub.DeepCopy()) + if err != nil { + return err + } + + return c.UpdateDomainMapping(ctx, updatedSource) +} + +// DeleteDomainMapping deletes DomainMapping by name +func (cl *knServingClient) DeleteDomainMapping(ctx context.Context, name string) error { + err := cl.client.DomainMappings(cl.namespace).Delete(ctx, name, v1.DeleteOptions{}) + if err != nil { + return knerrors.GetError(err) + } + return nil +} + +// ListDomainMappings lists all DomainMappings +func (cl *knServingClient) ListDomainMappings(ctx context.Context) (*servingv1alpha1.DomainMappingList, error) { + domainMappingList, err := cl.client.DomainMappings(cl.namespace).List(ctx, v1.ListOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + dmListNew := domainMappingList.DeepCopy() + err = updateServingGvk(dmListNew) + if err != nil { + return nil, err + } + dmListNew.Items = make([]servingv1alpha1.DomainMapping, len(domainMappingList.Items)) + for idx, domainMapping := range domainMappingList.Items { + domainMappingClone := domainMapping.DeepCopy() + err := updateServingGvk(domainMappingClone) + if err != nil { + return nil, err + } + dmListNew.Items[idx] = *domainMappingClone + } + return dmListNew, nil +} + +func updateServingGvk(obj runtime.Object) error { + return util.UpdateGroupVersionKindWithScheme(obj, servingv1alpha1.SchemeGroupVersion, scheme.Scheme) +} + +// DomainMappingBuilder is for building the domainMapping +type DomainMappingBuilder struct { + domainMapping *servingv1alpha1.DomainMapping +} + +// NewDomainMappingBuilder for building domainMapping object +func NewDomainMappingBuilder(name string) *DomainMappingBuilder { + return &DomainMappingBuilder{domainMapping: &servingv1alpha1.DomainMapping{ + ObjectMeta: v1.ObjectMeta{ + Name: name, + }, + }} +} + +// Namespace for domainMapping builder +func (b *DomainMappingBuilder) Namespace(ns string) *DomainMappingBuilder { + b.domainMapping.Namespace = ns + return b +} + +// Reference for domainMapping builder +func (b *DomainMappingBuilder) Reference(reference duckv1.KReference) *DomainMappingBuilder { + b.domainMapping.Spec.Ref = reference + return b +} + +// TLS for domainMapping builder +func (b *DomainMappingBuilder) TLS(cert string) *DomainMappingBuilder { + if cert == "" { + return b + } + b.domainMapping.Spec.TLS = &servingv1alpha1.SecretTLS{SecretName: cert} + return b +} + +// Build to return an instance of domainMapping object +func (b *DomainMappingBuilder) Build() *servingv1alpha1.DomainMapping { + return b.domainMapping +} diff --git a/vendor/knative.dev/client-pkg/pkg/sources/v1/apiserver_client.go b/vendor/knative.dev/client-pkg/pkg/sources/v1/apiserver_client.go new file mode 100644 index 0000000000..f84d3bcff4 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/sources/v1/apiserver_client.go @@ -0,0 +1,218 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + knerrors "knative.dev/client-pkg/pkg/errors" + "knative.dev/client-pkg/pkg/util" + + v1 "knative.dev/eventing/pkg/apis/sources/v1" + "knative.dev/eventing/pkg/client/clientset/versioned/scheme" + clientv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +// KnAPIServerSourcesClient interface for working with ApiServer sources +type KnAPIServerSourcesClient interface { + + // Get an ApiServerSource by name + GetAPIServerSource(ctx context.Context, name string) (*v1.ApiServerSource, error) + + // Create an ApiServerSource by object + CreateAPIServerSource(ctx context.Context, apiSource *v1.ApiServerSource) error + + // Update an ApiServerSource by object + UpdateAPIServerSource(ctx context.Context, apiSource *v1.ApiServerSource) error + + // Delete an ApiServerSource by name + DeleteAPIServerSource(ctx context.Context, name string) error + + // List ApiServerSource + // TODO: Support list configs like in service list + ListAPIServerSource(ctx context.Context) (*v1.ApiServerSourceList, error) + + // Get namespace for this client + Namespace() string +} + +// knSourcesClient is a combination of Sources client interface and namespace +// Temporarily help to add sources dependencies +// May be changed when adding real sources features +type apiServerSourcesClient struct { + client clientv1.ApiServerSourceInterface + namespace string +} + +// newKnAPIServerSourcesClient is to invoke Eventing Sources Client API to create object +func newKnAPIServerSourcesClient(client clientv1.ApiServerSourceInterface, namespace string) KnAPIServerSourcesClient { + return &apiServerSourcesClient{ + client: client, + namespace: namespace, + } +} + +// GetAPIServerSource returns apiSource object if present +func (c *apiServerSourcesClient) GetAPIServerSource(ctx context.Context, name string) (*v1.ApiServerSource, error) { + apiSource, err := c.client.Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + err = updateSourceGVK(apiSource) + if err != nil { + return nil, err + } + return apiSource, nil +} + +// CreateAPIServerSource is used to create an instance of ApiServerSource +func (c *apiServerSourcesClient) CreateAPIServerSource(ctx context.Context, apiSource *v1.ApiServerSource) error { + _, err := c.client.Create(ctx, apiSource, metav1.CreateOptions{}) + if err != nil { + return knerrors.GetError(err) + } + + return nil +} + +// UpdateAPIServerSource is used to update an instance of ApiServerSource +func (c *apiServerSourcesClient) UpdateAPIServerSource(ctx context.Context, apiSource *v1.ApiServerSource) error { + _, err := c.client.Update(ctx, apiSource, metav1.UpdateOptions{}) + if err != nil { + return knerrors.GetError(err) + } + + return nil +} + +// DeleteAPIServerSource is used to create an instance of ApiServerSource +func (c *apiServerSourcesClient) DeleteAPIServerSource(ctx context.Context, name string) error { + err := c.client.Delete(ctx, name, metav1.DeleteOptions{}) + if err != nil { + return knerrors.GetError(err) + } + return nil +} + +// Return the client's namespace +func (c *apiServerSourcesClient) Namespace() string { + return c.namespace +} + +// ListAPIServerSource returns the available ApiServer type sources +func (c *apiServerSourcesClient) ListAPIServerSource(ctx context.Context) (*v1.ApiServerSourceList, error) { + sourceList, err := c.client.List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + + return updateAPIServerSourceListGVK(sourceList) +} + +func updateAPIServerSourceListGVK(sourceList *v1.ApiServerSourceList) (*v1.ApiServerSourceList, error) { + sourceListNew := sourceList.DeepCopy() + err := updateSourceGVK(sourceListNew) + if err != nil { + return nil, err + } + + sourceListNew.Items = make([]v1.ApiServerSource, len(sourceList.Items)) + for idx, source := range sourceList.Items { + sourceClone := source.DeepCopy() + err := updateSourceGVK(sourceClone) + if err != nil { + return nil, err + } + sourceListNew.Items[idx] = *sourceClone + } + return sourceListNew, nil +} + +func updateSourceGVK(obj runtime.Object) error { + return util.UpdateGroupVersionKindWithScheme(obj, v1.SchemeGroupVersion, scheme.Scheme) +} + +// APIServerSourceBuilder is for building the source +type APIServerSourceBuilder struct { + apiServerSource *v1.ApiServerSource +} + +// NewAPIServerSourceBuilder for building ApiServer source object +func NewAPIServerSourceBuilder(name string) *APIServerSourceBuilder { + return &APIServerSourceBuilder{apiServerSource: &v1.ApiServerSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + }} +} + +// NewAPIServerSourceBuilderFromExisting for building the object from existing ApiServerSource object +func NewAPIServerSourceBuilderFromExisting(apiServerSource *v1.ApiServerSource) *APIServerSourceBuilder { + return &APIServerSourceBuilder{apiServerSource: apiServerSource.DeepCopy()} +} + +// Resources which should be streamed +func (b *APIServerSourceBuilder) Resources(resources []v1.APIVersionKindSelector) *APIServerSourceBuilder { + b.apiServerSource.Spec.Resources = resources + return b +} + +// ServiceAccount with which this source should operate +func (b *APIServerSourceBuilder) ServiceAccount(sa string) *APIServerSourceBuilder { + b.apiServerSource.Spec.ServiceAccountName = sa + return b +} + +// EventMode for whether to send resource 'Ref' or complete 'Resource' +func (b *APIServerSourceBuilder) EventMode(eventMode string) *APIServerSourceBuilder { + b.apiServerSource.Spec.EventMode = eventMode + return b +} + +// Sink or destination of the source +func (b *APIServerSourceBuilder) Sink(sink duckv1.Destination) *APIServerSourceBuilder { + b.apiServerSource.Spec.Sink = sink + return b +} + +// CloudEventOverrides adds given Cloud Event override extensions map to source spec +func (b *APIServerSourceBuilder) CloudEventOverrides(ceo map[string]string, toRemove []string) *APIServerSourceBuilder { + if ceo == nil && len(toRemove) == 0 { + return b + } + + ceOverrides := b.apiServerSource.Spec.CloudEventOverrides + if ceOverrides == nil { + ceOverrides = &duckv1.CloudEventOverrides{Extensions: map[string]string{}} + b.apiServerSource.Spec.CloudEventOverrides = ceOverrides + } + for k, v := range ceo { + ceOverrides.Extensions[k] = v + } + for _, r := range toRemove { + delete(ceOverrides.Extensions, r) + } + + return b +} + +// Build the ApiServerSource object +func (b *APIServerSourceBuilder) Build() *v1.ApiServerSource { + return b.apiServerSource +} diff --git a/vendor/knative.dev/client-pkg/pkg/sources/v1/apiserver_client_mock.go b/vendor/knative.dev/client-pkg/pkg/sources/v1/apiserver_client_mock.go new file mode 100644 index 0000000000..9fffb66bad --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/sources/v1/apiserver_client_mock.go @@ -0,0 +1,120 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + "context" + "testing" + + v1 "knative.dev/eventing/pkg/apis/sources/v1" + + "knative.dev/client-pkg/pkg/util/mock" +) + +// MockKnAPIServerSourceClient for mocking the client +type MockKnAPIServerSourceClient struct { + t *testing.T + recorder *APIServerSourcesRecorder +} + +// NewMockKnAPIServerSourceClient returns a new mock instance which you need to record for +func NewMockKnAPIServerSourceClient(t *testing.T, ns ...string) *MockKnAPIServerSourceClient { + namespace := "default" + if len(ns) > 0 { + namespace = ns[0] + } + return &MockKnAPIServerSourceClient{ + t: t, + recorder: &APIServerSourcesRecorder{mock.NewRecorder(t, namespace)}, + } +} + +// Ensure that the interface is implemented +var _ KnAPIServerSourcesClient = &MockKnAPIServerSourceClient{} + +// APIServerSourcesRecorder for recording actions on source +type APIServerSourcesRecorder struct { + r *mock.Recorder +} + +// Recorder returns the recorder for registering API calls +func (c *MockKnAPIServerSourceClient) Recorder() *APIServerSourcesRecorder { + return c.recorder +} + +// Namespace of this client +func (c *MockKnAPIServerSourceClient) Namespace() string { + return c.recorder.r.Namespace() +} + +// GetAPIServerSource records a call for GetApiServerSource with the expected object or error. Either apiServerSource or err should be nil +func (sr *APIServerSourcesRecorder) GetAPIServerSource(name interface{}, apiServerSource *v1.ApiServerSource, err error) { + sr.r.Add("GetApiServerSource", []interface{}{name}, []interface{}{apiServerSource, err}) +} + +// GetAPIServerSource performs a previously recorded action, failing if non has been registered +func (c *MockKnAPIServerSourceClient) GetAPIServerSource(ctx context.Context, name string) (*v1.ApiServerSource, error) { + call := c.recorder.r.VerifyCall("GetApiServerSource", name) + return call.Result[0].(*v1.ApiServerSource), mock.ErrorOrNil(call.Result[1]) +} + +// CreateAPIServerSource records a call for CreateApiServerSource with the expected error +func (sr *APIServerSourcesRecorder) CreateAPIServerSource(apiServerSource interface{}, err error) { + sr.r.Add("CreateApiServerSource", []interface{}{apiServerSource}, []interface{}{err}) +} + +// CreateAPIServerSource performs a previously recorded action, failing if non has been registered +func (c *MockKnAPIServerSourceClient) CreateAPIServerSource(ctx context.Context, apiServerSource *v1.ApiServerSource) error { + call := c.recorder.r.VerifyCall("CreateApiServerSource", apiServerSource) + return mock.ErrorOrNil(call.Result[0]) +} + +// UpdateAPIServerSource records a call for UpdateAPIServerSource with the expected error (nil if none) +func (sr *APIServerSourcesRecorder) UpdateAPIServerSource(apiServerSource interface{}, err error) { + sr.r.Add("UpdateAPIServerSource", []interface{}{apiServerSource}, []interface{}{err}) +} + +// UpdateAPIServerSource performs a previously recorded action, failing if non has been registered +func (c *MockKnAPIServerSourceClient) UpdateAPIServerSource(ctx context.Context, apiServerSource *v1.ApiServerSource) error { + call := c.recorder.r.VerifyCall("UpdateAPIServerSource", apiServerSource) + return mock.ErrorOrNil(call.Result[0]) +} + +// DeleteAPIServerSource records a call for DeleteAPIServerSource with the expected error (nil if none) +func (sr *APIServerSourcesRecorder) DeleteAPIServerSource(name interface{}, err error) { + sr.r.Add("DeleteAPIServerSource", []interface{}{name}, []interface{}{err}) +} + +// DeleteAPIServerSource performs a previously recorded action, failing if non has been registered +func (c *MockKnAPIServerSourceClient) DeleteAPIServerSource(ctx context.Context, name string) error { + call := c.recorder.r.VerifyCall("DeleteAPIServerSource", name) + return mock.ErrorOrNil(call.Result[0]) +} + +// ListAPIServerSource records a call for ListAPIServerSource with the expected error (nil if none) +func (sr *APIServerSourcesRecorder) ListAPIServerSource(apiJobSourceList *v1.ApiServerSourceList, err error) { + sr.r.Add("ListAPIServerSource", []interface{}{}, []interface{}{apiJobSourceList, err}) +} + +// ListAPIServerSource performs a previously recorded action, failing if non has been registered +func (c *MockKnAPIServerSourceClient) ListAPIServerSource(context.Context) (*v1.ApiServerSourceList, error) { + call := c.recorder.r.VerifyCall("ListAPIServerSource") + return call.Result[0].(*v1.ApiServerSourceList), mock.ErrorOrNil(call.Result[1]) +} + +// Validate validates whether every recorded action has been called +func (sr *APIServerSourcesRecorder) Validate() { + sr.r.CheckThatAllRecordedMethodsHaveBeenCalled() +} diff --git a/vendor/knative.dev/client-pkg/pkg/sources/v1/binding_client.go b/vendor/knative.dev/client-pkg/pkg/sources/v1/binding_client.go new file mode 100644 index 0000000000..fd197dfe96 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/sources/v1/binding_client.go @@ -0,0 +1,277 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + "context" + "fmt" + + apisv1 "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + v1 "knative.dev/eventing/pkg/apis/sources/v1" + "knative.dev/eventing/pkg/client/clientset/versioned/scheme" + clientv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1" + duckv1 "knative.dev/pkg/apis/duck/v1" + "knative.dev/pkg/tracker" + + knerrors "knative.dev/client-pkg/pkg/errors" + "knative.dev/client-pkg/pkg/util" +) + +// KnSinkBindingClient to Eventing Sources. All methods are relative to the +// namespace specified during construction +type KnSinkBindingClient interface { + // Namespace in which this client is operating for + Namespace() string + // CreateSinkBinding is used to create an instance of binding + CreateSinkBinding(ctx context.Context, binding *v1.SinkBinding) error + // DeleteSinkBinding is used to delete an instance of binding + DeleteSinkBinding(ctx context.Context, name string) error + // GetSinkBinding is used to get an instance of binding + GetSinkBinding(ctx context.Context, name string) (*v1.SinkBinding, error) + // ListSinkBinding returns list of binding CRDs + ListSinkBindings(ctx context.Context) (*v1.SinkBindingList, error) + // UpdateSinkBinding is used to update an instance of binding + UpdateSinkBinding(ctx context.Context, binding *v1.SinkBinding) error +} + +// KnSinkBindingClient is a combination of Sources client interface and namespace +// Temporarily help to add sources dependencies +// May be changed when adding real sources features +type knBindingClient struct { + client clientv1.SinkBindingInterface + namespace string +} + +// NewKnSourcesClient is to invoke Eventing Sources Client API to create object +func newKnSinkBindingClient(client clientv1.SinkBindingInterface, namespace string) KnSinkBindingClient { + return &knBindingClient{ + client: client, + namespace: namespace, + } +} + +// CreateSinkBinding is used to create an instance of binding +func (c *knBindingClient) CreateSinkBinding(ctx context.Context, binding *v1.SinkBinding) error { + _, err := c.client.Create(ctx, binding, metav1.CreateOptions{}) + if err != nil { + return knerrors.GetError(err) + } + return nil +} + +// DeleteSinkBinding is used to delete an instance of binding +func (c *knBindingClient) DeleteSinkBinding(ctx context.Context, name string) error { + err := c.client.Delete(ctx, name, apisv1.DeleteOptions{}) + if err != nil { + return knerrors.GetError(err) + } + return nil +} + +// GetSinkBinding is used to get an instance of binding +func (c *knBindingClient) GetSinkBinding(ctx context.Context, name string) (*v1.SinkBinding, error) { + binding, err := c.client.Get(ctx, name, apisv1.GetOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + err = updateSinkBindingGvk(binding) + if err != nil { + return nil, err + } + return binding, nil +} + +func (c *knBindingClient) ListSinkBindings(ctx context.Context) (*v1.SinkBindingList, error) { + bindingList, err := c.client.List(ctx, apisv1.ListOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + bindingListNew := bindingList.DeepCopy() + err = updateSinkBindingGvk(bindingListNew) + if err != nil { + return nil, err + } + + bindingListNew.Items = make([]v1.SinkBinding, len(bindingList.Items)) + for idx, binding := range bindingList.Items { + bindingClone := binding.DeepCopy() + err := updateSinkBindingGvk(bindingClone) + if err != nil { + return nil, err + } + bindingListNew.Items[idx] = *bindingClone + } + return bindingListNew, nil +} + +// CreateSinkBinding is used to create an instance of binding +func (c *knBindingClient) UpdateSinkBinding(ctx context.Context, binding *v1.SinkBinding) error { + _, err := c.client.Update(ctx, binding, metav1.UpdateOptions{}) + if err != nil { + return knerrors.GetError(err) + } + return nil +} + +// Return the client's namespace +func (c *knBindingClient) Namespace() string { + return c.namespace +} + +// update with the v1 group + version +func updateSinkBindingGvk(obj runtime.Object) error { + return util.UpdateGroupVersionKindWithScheme(obj, v1.SchemeGroupVersion, scheme.Scheme) +} + +// SinkBindingBuilder is for building the binding +type SinkBindingBuilder struct { + binding *v1.SinkBinding + sGvk *schema.GroupVersionKind + sName string + sLabelSelector map[string]string + sNamespace string + + // When set directly: + subject *tracker.Reference +} + +// NewSinkBindingBuilder for building binding object +func NewSinkBindingBuilder(name string) *SinkBindingBuilder { + return &SinkBindingBuilder{binding: &v1.SinkBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + }} +} + +// NewSinkBindingBuilderFromExisting for building the object from existing SinkBinding object +func NewSinkBindingBuilderFromExisting(binding *v1.SinkBinding) *SinkBindingBuilder { + return &SinkBindingBuilder{binding: binding.DeepCopy()} +} + +// Namespace for this binding +func (b *SinkBindingBuilder) Namespace(ns string) *SinkBindingBuilder { + b.binding.Namespace = ns + return b +} + +// Subscriber for the binding to send to (it's a Sink actually) +func (b *SinkBindingBuilder) Subject(subject *tracker.Reference) *SinkBindingBuilder { + b.subject = subject + return b +} + +// Add a GVK of the subject +func (b *SinkBindingBuilder) SubjectGVK(gvk *schema.GroupVersionKind) *SinkBindingBuilder { + b.sGvk = gvk + return b +} + +// Add a subject name for building up the name +func (b *SinkBindingBuilder) SubjectName(name string) *SinkBindingBuilder { + b.sName = name + return b +} + +// Add a subject namespace for building up the name +func (b *SinkBindingBuilder) SubjectNamespace(ns string) *SinkBindingBuilder { + b.sNamespace = ns + return b +} + +// Add a label match part for building up the subject +func (b *SinkBindingBuilder) AddSubjectMatchLabel(labelKey, labelValue string) *SinkBindingBuilder { + if b.sLabelSelector == nil { + b.sLabelSelector = map[string]string{} + } + b.sLabelSelector[labelKey] = labelValue + return b +} + +// Broker to set the broker of binding object +func (b *SinkBindingBuilder) Sink(sink *duckv1.Destination) *SinkBindingBuilder { + b.binding.Spec.Sink = *sink + return b +} + +// CloudEventOverrides adds given Cloud Event override extensions map to source spec +func (b *SinkBindingBuilder) CloudEventOverrides(ceo map[string]string, toRemove []string) *SinkBindingBuilder { + if ceo == nil && len(toRemove) == 0 { + return b + } + + ceOverrides := b.binding.Spec.CloudEventOverrides + if ceOverrides == nil { + ceOverrides = &duckv1.CloudEventOverrides{Extensions: map[string]string{}} + b.binding.Spec.CloudEventOverrides = ceOverrides + } + for k, v := range ceo { + ceOverrides.Extensions[k] = v + } + for _, r := range toRemove { + delete(ceOverrides.Extensions, r) + } + + return b +} + +// Build to return an instance of binding object +func (b *SinkBindingBuilder) Build() (*v1.SinkBinding, error) { + // If set directly, return the sink binding directly + if b.subject != nil { + b.binding.Spec.Subject = *b.subject + return b.binding, nil + } + + if b.sGvk == nil && b.sName == "" && b.sLabelSelector == nil { + // None of the subject methods has been called, so no subject build up + return b.binding, nil + } + + // Otherwise, validate and build up the subject + if b.sGvk == nil { + return nil, fmt.Errorf("no group-version-kind provided for creating binding %s", b.binding.Name) + } + + if b.sName != "" && b.sLabelSelector != nil { + return nil, fmt.Errorf("either a subject name or label selector can be used for creating binding %s, but not both (subject name: %s, label selector: %v", b.binding.Name, b.sName, b.sLabelSelector) + } + + subject := b.prepareBaseSubject() + if b.sName != "" { + subject.Name = b.sName + } else { + subject.Selector = &metav1.LabelSelector{ + MatchLabels: b.sLabelSelector, + } + } + + b.binding.Spec.Subject = subject + return b.binding, nil +} + +func (b *SinkBindingBuilder) prepareBaseSubject() tracker.Reference { + subject := tracker.Reference{ + APIVersion: b.sGvk.GroupVersion().String(), + Kind: b.sGvk.Kind, + } + if b.sNamespace != "" { + subject.Namespace = b.sNamespace + } + return subject +} diff --git a/vendor/knative.dev/client-pkg/pkg/sources/v1/binding_client_mock.go b/vendor/knative.dev/client-pkg/pkg/sources/v1/binding_client_mock.go new file mode 100644 index 0000000000..ab79482364 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/sources/v1/binding_client_mock.go @@ -0,0 +1,120 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + "context" + "testing" + + v1 "knative.dev/eventing/pkg/apis/sources/v1" + + "knative.dev/client-pkg/pkg/util/mock" +) + +// MockKnSinkBindingClient is a combine of test object and recorder +type MockKnSinkBindingClient struct { + t *testing.T + recorder *EventingRecorder +} + +// NewMockKnSinkBindingClient returns a new mock instance which you need to record for +func NewMockKnSinkBindingClient(t *testing.T, ns ...string) *MockKnSinkBindingClient { + namespace := "default" + if len(ns) > 0 { + namespace = ns[0] + } + return &MockKnSinkBindingClient{ + t: t, + recorder: &EventingRecorder{mock.NewRecorder(t, namespace)}, + } +} + +// Ensure that the interface is implemented +var _ KnSinkBindingClient = &MockKnSinkBindingClient{} + +// EventingRecorder is recorder for eventing objects +type EventingRecorder struct { + r *mock.Recorder +} + +// Recorder returns the recorder for registering API calls +func (c *MockKnSinkBindingClient) Recorder() *EventingRecorder { + return c.recorder +} + +// Namespace of this client +func (c *MockKnSinkBindingClient) Namespace() string { + return c.recorder.r.Namespace() +} + +// CreateSinkBinding records a call for CreateSinkBinding with the expected error +func (sr *EventingRecorder) CreateSinkBinding(binding interface{}, err error) { + sr.r.Add("CreateSinkBinding", []interface{}{binding}, []interface{}{err}) +} + +// CreateSinkBinding performs a previously recorded action +func (c *MockKnSinkBindingClient) CreateSinkBinding(ctx context.Context, binding *v1.SinkBinding) error { + call := c.recorder.r.VerifyCall("CreateSinkBinding", binding) + return mock.ErrorOrNil(call.Result[0]) +} + +// GetSinkBinding records a call for GetSinkBinding with the expected object or error. Either binding or err should be nil +func (sr *EventingRecorder) GetSinkBinding(name interface{}, binding *v1.SinkBinding, err error) { + sr.r.Add("GetSinkBinding", []interface{}{name}, []interface{}{binding, err}) +} + +// GetSinkBinding performs a previously recorded action +func (c *MockKnSinkBindingClient) GetSinkBinding(ctx context.Context, name string) (*v1.SinkBinding, error) { + call := c.recorder.r.VerifyCall("GetSinkBinding", name) + return call.Result[0].(*v1.SinkBinding), mock.ErrorOrNil(call.Result[1]) +} + +// DeleteSinkBinding records a call for DeleteSinkBinding with the expected error (nil if none) +func (sr *EventingRecorder) DeleteSinkBinding(name interface{}, err error) { + sr.r.Add("DeleteSinkBinding", []interface{}{name}, []interface{}{err}) +} + +// DeleteSinkBinding performs a previously recorded action, failing if non has been registered +func (c *MockKnSinkBindingClient) DeleteSinkBinding(ctx context.Context, name string) error { + call := c.recorder.r.VerifyCall("DeleteSinkBinding", name) + return mock.ErrorOrNil(call.Result[0]) +} + +// ListSinkBindings records a call for ListSinkBindings with the expected result and error (nil if none) +func (sr *EventingRecorder) ListSinkBindings(bindingList *v1.SinkBindingList, err error) { + sr.r.Add("ListSinkBindings", nil, []interface{}{bindingList, err}) +} + +// ListSinkBindings performs a previously recorded action +func (c *MockKnSinkBindingClient) ListSinkBindings(context.Context) (*v1.SinkBindingList, error) { + call := c.recorder.r.VerifyCall("ListSinkBindings") + return call.Result[0].(*v1.SinkBindingList), mock.ErrorOrNil(call.Result[1]) +} + +// UpdateSinkBinding records a call for ListSinkBindings with the expected result and error (nil if none) +func (sr *EventingRecorder) UpdateSinkBinding(binding interface{}, err error) { + sr.r.Add("UpdateSinkBinding", []interface{}{binding}, []interface{}{err}) +} + +// UpdateSinkBinding performs a previously recorded action +func (c *MockKnSinkBindingClient) UpdateSinkBinding(ctx context.Context, binding *v1.SinkBinding) error { + call := c.recorder.r.VerifyCall("UpdateSinkBinding") + return mock.ErrorOrNil(call.Result[0]) +} + +// Validate validates whether every recorded action has been called +func (sr *EventingRecorder) Validate() { + sr.r.CheckThatAllRecordedMethodsHaveBeenCalled() +} diff --git a/vendor/knative.dev/client-pkg/pkg/sources/v1/client.go b/vendor/knative.dev/client-pkg/pkg/sources/v1/client.go new file mode 100644 index 0000000000..dd6ee74172 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/sources/v1/client.go @@ -0,0 +1,63 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + clientv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1" +) + +// KnSinkBindingClient to Eventing Sources. All methods are relative to the +// namespace specified during construction +type KnSourcesClient interface { + // Get client for sink binding sources + SinkBindingClient() KnSinkBindingClient + + // Get client for ApiServer sources + APIServerSourcesClient() KnAPIServerSourcesClient + + // Get client for container sources + ContainerSourcesClient() KnContainerSourcesClient +} + +// sourcesClient is a combination of Sources client interface and namespace +// Temporarily help to add sources dependencies +// May be changed when adding real sources features +type sourcesClient struct { + client clientv1.SourcesV1Interface + namespace string +} + +// NewKnSourcesClient for managing all eventing built-in sources +func NewKnSourcesClient(client clientv1.SourcesV1Interface, namespace string) KnSourcesClient { + return &sourcesClient{ + client: client, + namespace: namespace, + } +} + +// ApiServerSourcesClient for dealing with ApiServer sources +func (c *sourcesClient) SinkBindingClient() KnSinkBindingClient { + return newKnSinkBindingClient(c.client.SinkBindings(c.namespace), c.namespace) +} + +// ApiServerSourcesClient for dealing with ApiServer sources +func (c *sourcesClient) APIServerSourcesClient() KnAPIServerSourcesClient { + return newKnAPIServerSourcesClient(c.client.ApiServerSources(c.namespace), c.namespace) +} + +// ApiServerSourcesClient for dealing with ApiServer sources +func (c *sourcesClient) ContainerSourcesClient() KnContainerSourcesClient { + return newKnContainerSourcesClient(c.client.ContainerSources(c.namespace), c.namespace) +} diff --git a/vendor/knative.dev/client-pkg/pkg/sources/v1/container_client.go b/vendor/knative.dev/client-pkg/pkg/sources/v1/container_client.go new file mode 100644 index 0000000000..7aaef5118f --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/sources/v1/container_client.go @@ -0,0 +1,215 @@ +/* +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/client-pkg/pkg/config" + + "k8s.io/client-go/util/retry" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + knerrors "knative.dev/client-pkg/pkg/errors" + "knative.dev/client-pkg/pkg/util" + v1 "knative.dev/eventing/pkg/apis/sources/v1" + "knative.dev/eventing/pkg/client/clientset/versioned/scheme" + clientv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +type ContainerUpdateFunc func(source *v1.ContainerSource) (*v1.ContainerSource, error) + +// KnContainerSourcesClient interface for working with ApiServer sources +type KnContainerSourcesClient interface { + + // Get an ContainerSource by name + GetContainerSource(ctx context.Context, name string) (*v1.ContainerSource, error) + + // Create an ContainerSource by object + CreateContainerSource(ctx context.Context, containerSrc *v1.ContainerSource) error + + // Update an ContainerSource by object + UpdateContainerSource(ctx context.Context, containerSrc *v1.ContainerSource) error + + // Update an ContainerSource by object and retry on conflict + UpdateContainerSourceWithRetry(ctx context.Context, name string, updateFunc ContainerUpdateFunc, nrRetries int) error + + // Delete an ContainerSource by name + DeleteContainerSource(name string, ctx context.Context) error + + // List ContainerSource + ListContainerSources(ctx context.Context) (*v1.ContainerSourceList, error) + + // Get namespace for this client + Namespace() string +} + +// knSourcesClient is a combination of Sources client interface and namespace +// Temporarily help to add sources dependencies +// May be changed when adding real sources features +type containerSourcesClient struct { + client clientv1.ContainerSourceInterface + namespace string +} + +func (c *containerSourcesClient) UpdateContainerSourceWithRetry(ctx context.Context, name string, updateFunc ContainerUpdateFunc, nrRetries int) error { + return updateContainerSourceWithRetry(ctx, c, name, updateFunc, nrRetries) +} + +func updateContainerSourceWithRetry(ctx context.Context, c KnContainerSourcesClient, name string, updateFunc ContainerUpdateFunc, nrRetries int) error { + b := config.DefaultRetry + b.Steps = nrRetries + err := retry.RetryOnConflict(b, func() error { + return updateContainerSource(ctx, c, name, updateFunc) + }) + return err +} + +func updateContainerSource(ctx context.Context, c KnContainerSourcesClient, name string, updateFunc ContainerUpdateFunc) error { + source, err := c.GetContainerSource(ctx, name) + if err != nil { + return err + } + if source.GetDeletionTimestamp() != nil { + return fmt.Errorf("can't update container source %s because it has been marked for deletion", name) + } + updatedSource, err := updateFunc(source.DeepCopy()) + if err != nil { + return err + } + + return c.UpdateContainerSource(ctx, updatedSource) +} + +// newKnContainerSourcesClient is to invoke Eventing Sources Client API to create object +func newKnContainerSourcesClient(client clientv1.ContainerSourceInterface, namespace string) KnContainerSourcesClient { + return &containerSourcesClient{ + client: client, + namespace: namespace, + } +} + +// GetContainerSource returns containerSrc object if present +func (c *containerSourcesClient) GetContainerSource(ctx context.Context, name string) (*v1.ContainerSource, error) { + containerSrc, err := c.client.Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + + return containerSrc, nil +} + +// CreateContainerSource is used to create an instance of ContainerSource +func (c *containerSourcesClient) CreateContainerSource(ctx context.Context, containerSrc *v1.ContainerSource) error { + _, err := c.client.Create(ctx, containerSrc, metav1.CreateOptions{}) + if err != nil { + return knerrors.GetError(err) + } + + return nil +} + +// UpdateContainerSource is used to update an instance of ContainerSource +func (c *containerSourcesClient) UpdateContainerSource(ctx context.Context, containerSrc *v1.ContainerSource) error { + _, err := c.client.Update(ctx, containerSrc, metav1.UpdateOptions{}) + if err != nil { + return knerrors.GetError(err) + } + + return nil +} + +// DeleteContainerSource is used to create an instance of ContainerSource +func (c *containerSourcesClient) DeleteContainerSource(name string, ctx context.Context) error { + return c.client.Delete(ctx, name, metav1.DeleteOptions{}) +} + +// Return the client's namespace +func (c *containerSourcesClient) Namespace() string { + return c.namespace +} + +// ListContainerSource returns the available container sources +func (c *containerSourcesClient) ListContainerSources(ctx context.Context) (*v1.ContainerSourceList, error) { + sourceList, err := c.client.List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + + containerListNew := sourceList.DeepCopy() + err = updateContainerSourceGvk(containerListNew) + if err != nil { + return nil, err + } + + containerListNew.Items = make([]v1.ContainerSource, len(sourceList.Items)) + for idx, binding := range sourceList.Items { + bindingClone := binding.DeepCopy() + err := updateSinkBindingGvk(bindingClone) + if err != nil { + return nil, err + } + containerListNew.Items[idx] = *bindingClone + } + + return containerListNew, nil +} + +// update with the v1 group + version +func updateContainerSourceGvk(obj runtime.Object) error { + return util.UpdateGroupVersionKindWithScheme(obj, v1.SchemeGroupVersion, scheme.Scheme) +} + +// ContainerSourceBuilder is for building the source +type ContainerSourceBuilder struct { + ContainerSource *v1.ContainerSource +} + +// NewContainerSourceBuilder for building Container source object +func NewContainerSourceBuilder(name string) *ContainerSourceBuilder { + return &ContainerSourceBuilder{ContainerSource: &v1.ContainerSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + }} +} + +// NewContainerSourceBuilderFromExisting for building the object from existing ContainerSource object +func NewContainerSourceBuilderFromExisting(ContainerSource *v1.ContainerSource) *ContainerSourceBuilder { + return &ContainerSourceBuilder{ContainerSource: ContainerSource.DeepCopy()} +} + +// Sink or destination of the source +func (b *ContainerSourceBuilder) Sink(sink duckv1.Destination) *ContainerSourceBuilder { + b.ContainerSource.Spec.Sink = sink + return b +} + +// Build the ContainerSource object +func (b *ContainerSourceBuilder) Build() *v1.ContainerSource { + return b.ContainerSource +} + +// PodSpec defines the PodSpec +func (b *ContainerSourceBuilder) PodSpec(podSpec corev1.PodSpec) *ContainerSourceBuilder { + b.ContainerSource.Spec.Template.Spec = podSpec + return b +} diff --git a/vendor/knative.dev/client-pkg/pkg/sources/v1/container_client_mock.go b/vendor/knative.dev/client-pkg/pkg/sources/v1/container_client_mock.go new file mode 100644 index 0000000000..59416e61d2 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/sources/v1/container_client_mock.go @@ -0,0 +1,127 @@ +/* +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" + "testing" + + "knative.dev/client-pkg/pkg/util/mock" + v1 "knative.dev/eventing/pkg/apis/sources/v1" +) + +// MockKnContainerSourceClient is a combine of test object and recorder +type MockKnContainerSourceClient struct { + t *testing.T + recorder *ConainterSourceRecorder + namespace string +} + +// NewMockKnContainerSourceClient returns a new mock instance which you need to record for +func NewMockKnContainerSourceClient(t *testing.T, ns ...string) *MockKnContainerSourceClient { + namespace := "default" + if len(ns) > 0 { + namespace = ns[0] + } + return &MockKnContainerSourceClient{ + t: t, + recorder: &ConainterSourceRecorder{mock.NewRecorder(t, namespace)}, + namespace: namespace, + } +} + +// Ensure that the interface is implemented +var _ KnContainerSourcesClient = &MockKnContainerSourceClient{} + +// ConainterSourceRecorder is recorder for eventing objects +type ConainterSourceRecorder struct { + r *mock.Recorder +} + +// Recorder returns the recorder for registering API calls +func (c *MockKnContainerSourceClient) Recorder() *ConainterSourceRecorder { + return c.recorder +} + +// Namespace of this client +func (c *MockKnContainerSourceClient) Namespace() string { + return c.recorder.r.Namespace() +} + +// CreateContainerSource records a call for CreateContainerSource with the expected error +func (sr *ConainterSourceRecorder) CreateContainerSource(binding interface{}, err error) { + sr.r.Add("CreateContainerSource", []interface{}{binding}, []interface{}{err}) +} + +// CreateContainerSource performs a previously recorded action +func (c *MockKnContainerSourceClient) CreateContainerSource(ctx context.Context, binding *v1.ContainerSource) error { + call := c.recorder.r.VerifyCall("CreateContainerSource", binding) + return mock.ErrorOrNil(call.Result[0]) +} + +// GetContainerSource records a call for GetContainerSource with the expected object or error. Either binding or err should be nil +func (sr *ConainterSourceRecorder) GetContainerSource(name interface{}, binding *v1.ContainerSource, err error) { + sr.r.Add("GetContainerSource", []interface{}{name}, []interface{}{binding, err}) +} + +// GetContainerSource performs a previously recorded action +func (c *MockKnContainerSourceClient) GetContainerSource(ctx context.Context, name string) (*v1.ContainerSource, error) { + call := c.recorder.r.VerifyCall("GetContainerSource", name) + return call.Result[0].(*v1.ContainerSource), mock.ErrorOrNil(call.Result[1]) +} + +// DeleteContainerSource records a call for DeleteContainerSource with the expected error (nil if none) +func (sr *ConainterSourceRecorder) DeleteContainerSource(name interface{}, err error) { + sr.r.Add("DeleteContainerSource", []interface{}{name}, []interface{}{err}) +} + +// DeleteContainerSource performs a previously recorded action, failing if non has been registered +func (c *MockKnContainerSourceClient) DeleteContainerSource(name string, ctx context.Context) error { + call := c.recorder.r.VerifyCall("DeleteContainerSource", name) + return mock.ErrorOrNil(call.Result[0]) +} + +// ListContainerSources records a call for ListContainerSources with the expected result and error (nil if none) +func (sr *ConainterSourceRecorder) ListContainerSources(bindingList *v1.ContainerSourceList, err error) { + sr.r.Add("ListContainerSources", nil, []interface{}{bindingList, err}) +} + +// ListContainerSources performs a previously recorded action +func (c *MockKnContainerSourceClient) ListContainerSources(context.Context) (*v1.ContainerSourceList, error) { + call := c.recorder.r.VerifyCall("ListContainerSources") + return call.Result[0].(*v1.ContainerSourceList), mock.ErrorOrNil(call.Result[1]) +} + +// UpdateContainerSource records a call for ListContainerSources with the expected result and error (nil if none) +func (sr *ConainterSourceRecorder) UpdateContainerSource(binding interface{}, err error) { + sr.r.Add("UpdateContainerSource", []interface{}{binding}, []interface{}{err}) +} + +// UpdateContainerSource performs a previously recorded action +func (c *MockKnContainerSourceClient) UpdateContainerSource(ctx context.Context, containerSrc *v1.ContainerSource) error { + call := c.recorder.r.VerifyCall("UpdateContainerSource") + return mock.ErrorOrNil(call.Result[0]) +} + +func (c *MockKnContainerSourceClient) UpdateContainerSourceWithRetry(ctx context.Context, name string, updateFunc ContainerUpdateFunc, nrRetries int) error { + return updateContainerSourceWithRetry(ctx, c, name, updateFunc, nrRetries) +} + +// Validate validates whether every recorded action has been called +func (sr *ConainterSourceRecorder) Validate() { + sr.r.CheckThatAllRecordedMethodsHaveBeenCalled() +} diff --git a/vendor/knative.dev/client-pkg/pkg/sources/v1beta2/client.go b/vendor/knative.dev/client-pkg/pkg/sources/v1beta2/client.go new file mode 100644 index 0000000000..0a9f37d8a9 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/sources/v1beta2/client.go @@ -0,0 +1,47 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1beta2 + +import ( + clientv1beta2 "knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1beta2" +) + +// KnSinkBindingClient to Eventing Sources. All methods are relative to the +// namespace specified during construction +type KnSourcesClient interface { + // Get client for Ping sources + PingSourcesClient() KnPingSourcesClient +} + +// sourcesClient is a combination of Sources client interface and namespace +// Temporarily help to add sources dependencies +// May be changed when adding real sources features +type sourcesClient struct { + client clientv1beta2.SourcesV1beta2Interface + namespace string +} + +// NewKnSourcesClient for managing all eventing built-in sources +func NewKnSourcesClient(client clientv1beta2.SourcesV1beta2Interface, namespace string) KnSourcesClient { + return &sourcesClient{ + client: client, + namespace: namespace, + } +} + +// Get the client for dealing with Ping sources +func (c *sourcesClient) PingSourcesClient() KnPingSourcesClient { + return newKnPingSourcesClient(c.client.PingSources(c.namespace), c.namespace) +} diff --git a/vendor/knative.dev/client-pkg/pkg/sources/v1beta2/ping_client.go b/vendor/knative.dev/client-pkg/pkg/sources/v1beta2/ping_client.go new file mode 100644 index 0000000000..2d0e1e94ba --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/sources/v1beta2/ping_client.go @@ -0,0 +1,249 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1beta2 + +import ( + "context" + "fmt" + + "knative.dev/client-pkg/pkg/config" + + "k8s.io/client-go/util/retry" + + "k8s.io/apimachinery/pkg/runtime" + "knative.dev/client-pkg/pkg/util" + "knative.dev/eventing/pkg/client/clientset/versioned/scheme" + + knerrors "knative.dev/client-pkg/pkg/errors" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + sourcesv1beta2 "knative.dev/eventing/pkg/apis/sources/v1beta2" + + clientv1beta2 "knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1beta2" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +type PingSourceUpdateFunc func(origSource *sourcesv1beta2.PingSource) (*sourcesv1beta2.PingSource, error) + +// Interface for interacting with a Ping source +type KnPingSourcesClient interface { + + // GetPingSource fetches a Ping source by its name + GetPingSource(ctx context.Context, name string) (*sourcesv1beta2.PingSource, error) + + // CreatePingSource creates a Ping source + CreatePingSource(ctx context.Context, pingSource *sourcesv1beta2.PingSource) error + + // UpdatePingSource updates a Ping source + UpdatePingSource(ctx context.Context, pingSource *sourcesv1beta2.PingSource) error + + // UpdatePingSourceWithRetry updates a Ping source and retries on conflict + UpdatePingSourceWithRetry(ctx context.Context, name string, updateFunc PingSourceUpdateFunc, nrRetries int) error + + // DeletePingSource deletes a Ping source + DeletePingSource(ctx context.Context, name string) error + + // ListPingSource lists all Ping sources + // TODO: Support list configs like in service list + ListPingSource(ctx context.Context) (*sourcesv1beta2.PingSourceList, error) + + // Get namespace for this source + Namespace() string +} + +// knSourcesClient is a combination of Sources client interface and namespace +// Temporarily help to add sources dependencies +// May be changed when adding real sources features +type pingSourcesClient struct { + client clientv1beta2.PingSourceInterface + namespace string +} + +// NewKnSourcesClient is to invoke Eventing Sources Client API to create object +func newKnPingSourcesClient(client clientv1beta2.PingSourceInterface, namespace string) KnPingSourcesClient { + return &pingSourcesClient{ + client: client, + namespace: namespace, + } +} + +// Get the namespace for which this client has been created +func (c *pingSourcesClient) Namespace() string { + return c.namespace +} + +func (c *pingSourcesClient) CreatePingSource(ctx context.Context, pingsource *sourcesv1beta2.PingSource) error { + if pingsource.Spec.Sink.Ref == nil && pingsource.Spec.Sink.URI == nil { + return fmt.Errorf("a sink is required for creating a source") + } + _, err := c.client.Create(ctx, pingsource, metav1.CreateOptions{}) + if err != nil { + return knerrors.GetError(err) + } + return nil +} + +func (c *pingSourcesClient) UpdatePingSource(ctx context.Context, pingSource *sourcesv1beta2.PingSource) error { + _, err := c.client.Update(ctx, pingSource, metav1.UpdateOptions{}) + if err != nil { + return knerrors.GetError(err) + } + return nil +} + +func (c *pingSourcesClient) UpdatePingSourceWithRetry(ctx context.Context, name string, updateFunc PingSourceUpdateFunc, nrRetries int) error { + return updatePingSourceWithRetry(ctx, c, name, updateFunc, nrRetries) +} + +func updatePingSourceWithRetry(ctx context.Context, c KnPingSourcesClient, name string, updateFunc PingSourceUpdateFunc, nrRetries int) error { + b := config.DefaultRetry + b.Steps = nrRetries + err := retry.RetryOnConflict(b, func() error { + return updatePingSource(ctx, c, name, updateFunc) + }) + return err +} + +func updatePingSource(ctx context.Context, c KnPingSourcesClient, name string, updateFunc PingSourceUpdateFunc) error { + source, err := c.GetPingSource(ctx, name) + if err != nil { + return err + } + if source.GetDeletionTimestamp() != nil { + return fmt.Errorf("can't update ping source %s because it has been marked for deletion", name) + } + updatedSource, err := updateFunc(source.DeepCopy()) + if err != nil { + return err + } + + return c.UpdatePingSource(ctx, updatedSource) +} + +func (c *pingSourcesClient) DeletePingSource(ctx context.Context, name string) error { + err := c.client.Delete(ctx, name, metav1.DeleteOptions{}) + if err != nil { + return knerrors.GetError(err) + } + return nil +} + +func (c *pingSourcesClient) GetPingSource(ctx context.Context, name string) (*sourcesv1beta2.PingSource, error) { + source, err := c.client.Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + err = updateSourceGVK(source) + if err != nil { + return nil, err + } + return source, nil +} + +// ListPingSource returns the available Ping sources +func (c *pingSourcesClient) ListPingSource(ctx context.Context) (*sourcesv1beta2.PingSourceList, error) { + sourceList, err := c.client.List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + + return updatePingSourceListGVK(sourceList) +} + +func updateSourceGVK(obj runtime.Object) error { + return util.UpdateGroupVersionKindWithScheme(obj, sourcesv1beta2.SchemeGroupVersion, scheme.Scheme) +} + +func updatePingSourceListGVK(sourceList *sourcesv1beta2.PingSourceList) (*sourcesv1beta2.PingSourceList, error) { + sourceListNew := sourceList.DeepCopy() + err := updateSourceGVK(sourceListNew) + if err != nil { + return nil, err + } + + sourceListNew.Items = make([]sourcesv1beta2.PingSource, len(sourceList.Items)) + for idx, source := range sourceList.Items { + sourceClone := source.DeepCopy() + err := updateSourceGVK(sourceClone) + if err != nil { + return nil, err + } + sourceListNew.Items[idx] = *sourceClone + } + return sourceListNew, nil +} + +// Builder for building up Ping sources + +type PingSourceBuilder struct { + pingSource *sourcesv1beta2.PingSource +} + +func NewPingSourceBuilder(name string) *PingSourceBuilder { + return &PingSourceBuilder{pingSource: &sourcesv1beta2.PingSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + }} +} + +func NewPingSourceBuilderFromExisting(pingsource *sourcesv1beta2.PingSource) *PingSourceBuilder { + return &PingSourceBuilder{pingSource: pingsource.DeepCopy()} +} + +func (b *PingSourceBuilder) Schedule(schedule string) *PingSourceBuilder { + b.pingSource.Spec.Schedule = schedule + return b +} + +func (b *PingSourceBuilder) Data(data string) *PingSourceBuilder { + b.pingSource.Spec.Data = data + return b +} + +func (b *PingSourceBuilder) DataBase64(data string) *PingSourceBuilder { + b.pingSource.Spec.DataBase64 = data + return b +} + +func (b *PingSourceBuilder) Sink(sink duckv1.Destination) *PingSourceBuilder { + b.pingSource.Spec.Sink = sink + return b +} + +// CloudEventOverrides adds given Cloud Event override extensions map to source spec +func (b *PingSourceBuilder) CloudEventOverrides(ceo map[string]string, toRemove []string) *PingSourceBuilder { + if ceo == nil && len(toRemove) == 0 { + return b + } + + ceOverrides := b.pingSource.Spec.CloudEventOverrides + if ceOverrides == nil { + ceOverrides = &duckv1.CloudEventOverrides{Extensions: map[string]string{}} + b.pingSource.Spec.CloudEventOverrides = ceOverrides + } + for k, v := range ceo { + ceOverrides.Extensions[k] = v + } + for _, r := range toRemove { + delete(ceOverrides.Extensions, r) + } + + return b +} + +func (b *PingSourceBuilder) Build() *sourcesv1beta2.PingSource { + return b.pingSource +} diff --git a/vendor/knative.dev/client-pkg/pkg/sources/v1beta2/ping_client_mock.go b/vendor/knative.dev/client-pkg/pkg/sources/v1beta2/ping_client_mock.go new file mode 100644 index 0000000000..42623f0369 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/sources/v1beta2/ping_client_mock.go @@ -0,0 +1,122 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1beta2 + +import ( + "context" + "testing" + + "knative.dev/client-pkg/pkg/util/mock" + sourcesv1beta2 "knative.dev/eventing/pkg/apis/sources/v1beta2" +) + +type MockKnPingSourceClient struct { + t *testing.T + recorder *PingSourcesRecorder +} + +// NewMockKnPingSourceClient returns a new mock instance which you need to record for +func NewMockKnPingSourceClient(t *testing.T, ns ...string) *MockKnPingSourceClient { + namespace := "default" + if len(ns) > 0 { + namespace = ns[0] + } + return &MockKnPingSourceClient{ + t: t, + recorder: &PingSourcesRecorder{mock.NewRecorder(t, namespace)}, + } +} + +// Ensure that the interface is implemented +var _ KnPingSourcesClient = &MockKnPingSourceClient{} + +// recorder for service +type PingSourcesRecorder struct { + r *mock.Recorder +} + +// Recorder returns the recorder for registering API calls +func (c *MockKnPingSourceClient) Recorder() *PingSourcesRecorder { + return c.recorder +} + +// Namespace of this client +func (c *MockKnPingSourceClient) Namespace() string { + return c.recorder.r.Namespace() +} + +// CreatePingSource records a call for CreatePingSource with the expected error +func (sr *PingSourcesRecorder) CreatePingSource(pingSource interface{}, err error) { + sr.r.Add("CreatePingSource", []interface{}{pingSource}, []interface{}{err}) +} + +// CreatePingSource performs a previously recorded action, failing if non has been registered +func (c *MockKnPingSourceClient) CreatePingSource(ctx context.Context, pingSource *sourcesv1beta2.PingSource) error { + call := c.recorder.r.VerifyCall("CreatePingSource", pingSource) + return mock.ErrorOrNil(call.Result[0]) +} + +// GetPingSource records a call for GetPingSource with the expected object or error. Either pingsource or err should be nil +func (sr *PingSourcesRecorder) GetPingSource(name interface{}, pingSource *sourcesv1beta2.PingSource, err error) { + sr.r.Add("GetPingSource", []interface{}{name}, []interface{}{pingSource, err}) +} + +// GetPingSource performs a previously recorded action, failing if non has been registered +func (c *MockKnPingSourceClient) GetPingSource(ctx context.Context, name string) (*sourcesv1beta2.PingSource, error) { + call := c.recorder.r.VerifyCall("GetPingSource", name) + return call.Result[0].(*sourcesv1beta2.PingSource), mock.ErrorOrNil(call.Result[1]) +} + +// UpdatePingSource records a call for UpdatePingSource with the expected error (nil if none) +func (sr *PingSourcesRecorder) UpdatePingSource(pingSource interface{}, err error) { + sr.r.Add("UpdatePingSource", []interface{}{pingSource}, []interface{}{err}) +} + +// UpdatePingSource performs a previously recorded action, failing if non has been registered +func (c *MockKnPingSourceClient) UpdatePingSource(ctx context.Context, pingSource *sourcesv1beta2.PingSource) error { + call := c.recorder.r.VerifyCall("UpdatePingSource", pingSource) + return mock.ErrorOrNil(call.Result[0]) +} + +func (c *MockKnPingSourceClient) UpdatePingSourceWithRetry(ctx context.Context, name string, updateFunc PingSourceUpdateFunc, nrRetries int) error { + return updatePingSourceWithRetry(ctx, c, name, updateFunc, nrRetries) +} + +// UpdatePingSource records a call for DeletePingSource with the expected error (nil if none) +func (sr *PingSourcesRecorder) DeletePingSource(name interface{}, err error) { + sr.r.Add("DeletePingSource", []interface{}{name}, []interface{}{err}) +} + +// DeletePingSource performs a previously recorded action, failing if non has been registered +func (c *MockKnPingSourceClient) DeletePingSource(ctx context.Context, name string) error { + call := c.recorder.r.VerifyCall("DeletePingSource", name) + return mock.ErrorOrNil(call.Result[0]) +} + +// ListPingSource records a call for ListPingSource with the expected error (nil if none) +func (sr *PingSourcesRecorder) ListPingSource(pingSourceList *sourcesv1beta2.PingSourceList, err error) { + sr.r.Add("ListPingSource", []interface{}{}, []interface{}{pingSourceList, err}) +} + +// ListPingSource performs a previously recorded action, failing if non has been registered +func (c *MockKnPingSourceClient) ListPingSource(context.Context) (*sourcesv1beta2.PingSourceList, error) { + call := c.recorder.r.VerifyCall("ListPingSource") + return call.Result[0].(*sourcesv1beta2.PingSourceList), mock.ErrorOrNil(call.Result[1]) +} + +// Validates validates whether every recorded action has been called +func (sr *PingSourcesRecorder) Validate() { + sr.r.CheckThatAllRecordedMethodsHaveBeenCalled() +} diff --git a/vendor/knative.dev/client-pkg/pkg/util/compare.go b/vendor/knative.dev/client-pkg/pkg/util/compare.go new file mode 100644 index 0000000000..4b7e76b292 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/util/compare.go @@ -0,0 +1,85 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package util + +import ( + "fmt" + "strings" + + "gotest.tools/v3/assert/cmp" +) + +// ContainsAll is a comparison utility, compares given substrings against +// target string and returns the gotest.tools/v3/assert/cmp.Comparison function. +// Provide target string as first arg, followed by any number of substring as args +func ContainsAll(target string, substrings ...string) cmp.Comparison { + return func() cmp.Result { + var missing []string + for _, sub := range substrings { + if !strings.Contains(target, sub) { + missing = append(missing, sub) + } + } + if len(missing) > 0 { + return cmp.ResultFailure(fmt.Sprintf("\nActual output: %s\nMissing strings: %s", target, strings.Join(missing[:], ", "))) + } + return cmp.ResultSuccess + } +} + +// Like ContainsAll but ignores the case when checking +func ContainsAllIgnoreCase(target string, substrings ...string) cmp.Comparison { + return func() cmp.Result { + var missing []string + lTarget := strings.ToLower(target) + for _, sub := range substrings { + if !strings.Contains(lTarget, strings.ToLower(sub)) { + missing = append(missing, sub) + } + } + if len(missing) > 0 { + return cmp.ResultFailure(fmt.Sprintf("\nActual output (lower-cased): %s\nMissing strings (lower-cased): %s", lTarget, strings.ToLower(strings.Join(missing[:], ", ")))) + } + return cmp.ResultSuccess + } +} + +// ContainsNone is a comparison utility, compares given substrings against +// target string and returns the gotest.tools/v3/assert/cmp.Comparison function. +// Provide target string as first arg, followed by any number of substring as args +func ContainsNone(target string, substrings ...string) cmp.Comparison { + return func() cmp.Result { + var contains []string + for _, sub := range substrings { + if strings.Contains(target, sub) { + contains = append(contains, sub) + } + } + if len(contains) > 0 { + return cmp.ResultFailure(fmt.Sprintf("\nActual output: %s\nContains strings: %s", target, strings.Join(contains[:], ", "))) + } + return cmp.ResultSuccess + } +} + +// SliceContainsIgnoreCase checks (case insensitive) if given target string is present in slice +func SliceContainsIgnoreCase(slice []string, target string) bool { + for _, each := range slice { + if strings.EqualFold(target, each) { + return true + } + } + return false +} diff --git a/vendor/knative.dev/client-pkg/pkg/util/corev1_helper.go b/vendor/knative.dev/client-pkg/pkg/util/corev1_helper.go new file mode 100644 index 0000000000..d0a08892cc --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/util/corev1_helper.go @@ -0,0 +1,88 @@ +/* +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 util + +import ( + "crypto/sha1" //nolint:gosec // Weak crypto is fine here, we use it for generating unique keys. + "fmt" + "strings" + "unicode" + + corev1 "k8s.io/api/core/v1" +) + +// EnvToMap is an utility function to translate between the API list form of env vars, and the +// more convenient map form. +func EnvToMap(vars []corev1.EnvVar) (map[string]string, error) { + result := map[string]string{} + for _, envVar := range vars { + _, present := result[envVar.Name] + if present { + return nil, fmt.Errorf("env var name present more than once: %v", envVar.Name) + } + result[envVar.Name] = envVar.Value + } + return result, nil +} + +// GenerateVolumeName generates a volume name with respect to a given path string. +// Current implementation basically sanitizes the path string by replacing "/" with "-" +// To reduce any chance of duplication, a checksum part generated from the path string is appended to the sanitized string. +// The volume name must follow the DNS label standard as defined in RFC 1123. This means the name must: +// - contain at most 63 characters +// - contain only lowercase alphanumeric characters or '-' +// - start with an alphanumeric character +// - end with an alphanumeric character +func GenerateVolumeName(path string) string { + builder := &strings.Builder{} + for idx, r := range path { + switch { + case unicode.IsLower(r) || unicode.IsDigit(r) || r == '-': + builder.WriteRune(r) + case unicode.IsUpper(r): + builder.WriteRune(unicode.ToLower(r)) + case r == '/': + if idx != 0 { + builder.WriteRune('-') + } + default: + builder.WriteRune('-') + } + } + + vname := appendCheckSum(builder.String(), path) + + // the name must start with an alphanumeric character + if !unicode.IsLetter(rune(vname[0])) && !unicode.IsNumber(rune(vname[0])) { + vname = "k-" + vname + } + + // contain at most 63 characters + if len(vname) > 63 { + // must end with an alphanumeric character + vname = fmt.Sprintf("%s-n", vname[0:61]) + } + + return vname +} + +func appendCheckSum(sanitizedString, path string) string { + //nolint:gosec // Weak crypto is fine here, we use it for generating unique keys. + checkSum := sha1.Sum([]byte(path)) + shortCheckSum := checkSum[0:4] + return fmt.Sprintf("%s-%x", sanitizedString, shortCheckSum) +} diff --git a/vendor/knative.dev/client-pkg/pkg/util/logging_http_transport.go b/vendor/knative.dev/client-pkg/pkg/util/logging_http_transport.go new file mode 100644 index 0000000000..02baf05a09 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/util/logging_http_transport.go @@ -0,0 +1,84 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package util + +import ( + "fmt" + "io" + "net/http" + "net/http/httputil" + "os" + + "k8s.io/apimachinery/pkg/util/sets" +) + +var ( + // sensitiveRequestHeaders are headers that will be redacted when logging requests. + sensitiveRequestHeaders = sets.NewString( + "Authorization", + "WWW-Authenticate", + "Cookie", + "Proxy-Authorization") +) + +type LoggingHttpTransport struct { + transport http.RoundTripper + stream io.Writer +} + +func NewLoggingTransport(transport http.RoundTripper) http.RoundTripper { + return &LoggingHttpTransport{transport, nil} +} + +func NewLoggingTransportWithStream(transport http.RoundTripper, s io.Writer) http.RoundTripper { + return &LoggingHttpTransport{transport, s} +} + +func (t *LoggingHttpTransport) RoundTrip(r *http.Request) (*http.Response, error) { + stream := t.stream + if stream == nil { + stream = os.Stderr + } + redacted := http.Header{} + for k, v := range r.Header { + if sensitiveRequestHeaders.Has(k) { + redacted[k] = v + r.Header.Set(k, "********") + } + } + reqBytes, err := httputil.DumpRequestOut(r, true) + if err != nil { + fmt.Fprintln(stream, "error dumping request:", err) + return nil, fmt.Errorf("dumping request: %w", err) + } + fmt.Fprintln(stream, "===== REQUEST =====") + fmt.Fprintln(stream, string(reqBytes)) + + for k, v := range redacted { + r.Header[k] = v + } + + resp, err := t.transport.RoundTrip(r) + if err != nil { + fmt.Fprintln(stream, "===== ERROR =====") + fmt.Fprintln(stream, err) + } else { + respBytes, _ := httputil.DumpResponse(resp, true) + fmt.Fprintln(stream, "===== RESPONSE =====") + fmt.Fprintln(stream, string(respBytes)) + fmt.Fprintln(stream, " * * * * * *") + } + return resp, err +} diff --git a/vendor/knative.dev/client-pkg/pkg/util/mock/mock_helper.go b/vendor/knative.dev/client-pkg/pkg/util/mock/mock_helper.go new file mode 100644 index 0000000000..bc2047022b --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/util/mock/mock_helper.go @@ -0,0 +1,131 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mock + +import ( + "fmt" + "reflect" + "testing" + + "gotest.tools/v3/assert" +) + +// Recorded method call +type ApiMethodCall struct { + Args []interface{} + Result []interface{} +} + +// Recorder for recording mock call +type Recorder struct { + + // Test object used for asserting + t *testing.T + + // List of recorded calls in order + recordedCalls map[string][]ApiMethodCall + + // Namespace for client + namespace string +} + +// Add a recorded api call the list of calls +func (r *Recorder) Add(name string, args []interface{}, result []interface{}) { + call := ApiMethodCall{args, result} + calls, ok := r.recordedCalls[name] + if !ok { + calls = make([]ApiMethodCall, 0) + r.recordedCalls[name] = calls + } + r.recordedCalls[name] = append(calls, call) +} + +// Get the next recorded call +func (r *Recorder) Shift(name string) (*ApiMethodCall, error) { + calls := r.recordedCalls[name] + if len(calls) == 0 { + return nil, fmt.Errorf("no call to '%s' recorded", name) + } + call, calls := calls[0], calls[1:] + r.recordedCalls[name] = calls + return &call, nil +} + +func NewRecorder(t *testing.T, namespace string) *Recorder { + return &Recorder{ + t: t, + recordedCalls: make(map[string][]ApiMethodCall), + namespace: namespace, + } +} + +func (r *Recorder) Namespace() string { + return r.namespace +} + +// Check if every method has been called +func (r *Recorder) CheckThatAllRecordedMethodsHaveBeenCalled() { + for k, v := range r.recordedCalls { + if len(v) > 0 { + r.t.Errorf("Recorded method \"%s\" not been called", k) + } + } +} + +// Verify given arguments against recorded arguments +func (r *Recorder) VerifyCall(name string, args ...interface{}) *ApiMethodCall { + call := r.getCall(name) + callArgs := call.Args + for i, arg := range args { + assert.Assert(r.t, len(callArgs) > i, "Internal: Invalid recording: Expected %d args, got %d", len(callArgs), len(args)) + fn := reflect.ValueOf(callArgs[i]) + fnType := fn.Type() + if fnType.Kind() == reflect.Func { + if fnType.NumIn() == 2 && + // It's an assertion function which takes a Testing as first parameter + fnType.In(0).AssignableTo(reflect.TypeOf(r.t)) { + fn.Call([]reflect.Value{reflect.ValueOf(r.t), reflect.ValueOf(arg)}) + } else { + assert.Assert(r.t, fnType.AssignableTo(reflect.TypeOf(arg))) + } + } else { + assert.DeepEqual(r.t, callArgs[i], arg) + } + } + return call +} + +// Get call and verify that it exist +func (r *Recorder) getCall(name string) *ApiMethodCall { + call, err := r.Shift(name) + assert.NilError(r.t, err, "invalid mock setup, missing recording step") + return call +} + +// ===================================================================== +// Helper methods + +// mock.Any() can be used in recording to not check for the argument +func Any() func(t *testing.T, a interface{}) { + return func(t *testing.T, a interface{}) {} +} + +// Helper method to cast to an error if given +func ErrorOrNil(err interface{}) error { + if err == nil { + return nil + } + return err.(error) +} diff --git a/vendor/knative.dev/client-pkg/pkg/util/orderedmap.go b/vendor/knative.dev/client-pkg/pkg/util/orderedmap.go new file mode 100644 index 0000000000..90be29f85d --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/util/orderedmap.go @@ -0,0 +1,147 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package util + +type valueEntry struct { + Index int + Value interface{} +} + +type orderedMapIterator struct { + orderedMap *OrderedMap + nextIndex int +} + +// OrderedMap is similar implementation of OrderedDict in Python. +type OrderedMap struct { + Keys []string + ValueMap map[string]*valueEntry +} + +// NewOrderedMap returns new empty ordered map +func NewOrderedMap() *OrderedMap { + return &OrderedMap{ + Keys: []string{}, + ValueMap: map[string]*valueEntry{}, + } +} + +// NewOrderedMapWithKVStrings returns new empty ordered map +func NewOrderedMapWithKVStrings(kvList [][]string) *OrderedMap { + o := &OrderedMap{ + Keys: []string{}, + ValueMap: map[string]*valueEntry{}, + } + + for _, pair := range kvList { + if len(pair) != 2 { + return nil + } + + o.Set(pair[0], pair[1]) + } + return o +} + +// Get returns a value corresponding the key +func (o *OrderedMap) Get(key string) (interface{}, bool) { + ve, ok := o.ValueMap[key] + if ve != nil { + return ve.Value, ok + } else { + return nil, false + } +} + +// GetString returns a string value corresponding the key +func (o *OrderedMap) GetString(key string) (string, bool) { + ve, ok := o.ValueMap[key] + + if ve != nil { + return ve.Value.(string), ok + } else { + return "", false + } +} + +// GetStringWithDefault returns a string value corresponding the key if the key is existing. +// Otherwise, the default value is returned. +func (o *OrderedMap) GetStringWithDefault(key string, defaultValue string) string { + if ve, ok := o.ValueMap[key]; ok { + return ve.Value.(string) + } else { + return defaultValue + } +} + +// Set append the key and value if the key is not existing on the map +// Otherwise, the value does just replace the old value corresponding to the key. +func (o *OrderedMap) Set(key string, value interface{}) { + if ve, ok := o.ValueMap[key]; !ok { + o.Keys = append(o.Keys, key) + o.ValueMap[key] = &valueEntry{ + Index: len(o.Keys) - 1, + Value: value, + } + } else { + ve.Value = value + } +} + +// Delete deletes the key and value from the map +func (o *OrderedMap) Delete(key string) { + if ve, ok := o.ValueMap[key]; ok { + delete(o.ValueMap, key) + o.Keys = append(o.Keys[:ve.Index], o.Keys[ve.Index+1:]...) + } +} + +// Len returns a size of the ordered map +func (o *OrderedMap) Len() int { + return len(o.Keys) +} + +// Iterator creates a iterator object +func (o *OrderedMap) Iterator() *orderedMapIterator { + return &orderedMapIterator{ + orderedMap: o, + nextIndex: 0, + } +} + +// Next returns key and values on current iterating cursor. +// If the cursor moved over last entry, then the third return value will be false, otherwise true. +func (it *orderedMapIterator) Next() (string, interface{}, bool) { + if it.nextIndex >= it.orderedMap.Len() { + return "", nil, false + } + + key := it.orderedMap.Keys[it.nextIndex] + ve := it.orderedMap.ValueMap[key] + + it.nextIndex++ + + return key, ve.Value, true +} + +// NextString is the same with Next, but the value is returned as string +func (it *orderedMapIterator) NextString() (string, string, bool) { + key, value, isValid := it.Next() + if isValid { + return key, value.(string), isValid + } else { + return "", "", isValid + } +} diff --git a/vendor/knative.dev/client-pkg/pkg/util/parsing_helper.go b/vendor/knative.dev/client-pkg/pkg/util/parsing_helper.go new file mode 100644 index 0000000000..c10bdbd256 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/util/parsing_helper.go @@ -0,0 +1,202 @@ +// Copyright © 2019-2021 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 util + +import ( + "bufio" + "fmt" + "os" + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "knative.dev/pkg/tracker" +) + +// GetEnvsFromFile transform a path to a file containing environment variable into a list of key-value pair. +// If there is an issue reading the file or parsing the content in the file an error value will be returned. +func GetEnvsFromFile(filepath string, delimiter string) ([]string, error) { + envs := []string{} + file, err := os.Open(filepath) + if err != nil { + return envs, err + } + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + if len(line) == 0 { + continue + } + envs = append(envs, scanner.Text()) + } + return envs, nil +} + +// OrderedMapAndRemovalListFromArray creates a list of key-value pair using MapFromArrayAllowingSingles, and a list of removal entries +func OrderedMapAndRemovalListFromArray(arr []string, delimiter string) (*OrderedMap, []string, error) { + orderedMap := NewOrderedMap() + removalList := []string{} + + for _, pairStr := range arr { + pairSlice := strings.SplitN(pairStr, delimiter, 2) + if len(pairSlice) == 0 || (len(pairSlice) == 1 && !strings.HasSuffix(pairSlice[0], "-")) { + return nil, nil, fmt.Errorf("argument requires a value that contains the %q character; got %q", delimiter, pairStr) + } + key := pairSlice[0] + if len(pairSlice) == 2 { + value := pairSlice[1] + orderedMap.Set(key, value) + } else { + // error cases are already filtered out from above part + removalList = append(removalList, key[:len(key)-1]) + } + } + + return orderedMap, removalList, nil +} + +func MapFromArrayAllowingSingles(arr []string, delimiter string) (map[string]string, error) { + return mapFromArray(arr, delimiter, true) +} + +func MapFromArray(arr []string, delimiter string) (map[string]string, error) { + return mapFromArray(arr, delimiter, false) +} + +func Add(original *map[string]string, toAdd map[string]string, toRemove []string) map[string]string { + for k, v := range toAdd { + (*original)[k] = v + } + for _, k := range toRemove { + delete(*original, k) + } + return *original +} + +func ParseMinusSuffix(m map[string]string) []string { + stringToRemove := []string{} + for key := range m { + if strings.HasSuffix(key, "-") { + stringToRemove = append(stringToRemove, key[:len(key)-1]) + delete(m, key) + } + } + return stringToRemove +} + +// StringMap is a map which key and value are strings +type StringMap map[string]string + +// Merge to merge a map to a StringMap +func (m StringMap) Merge(toMerge map[string]string) StringMap { + for k, v := range toMerge { + m[k] = v + } + return m +} + +// Remove to remove from StringMap +func (m StringMap) Remove(toRemove []string) StringMap { + for _, k := range toRemove { + delete(m, k) + } + return m +} + +// AddedAndRemovalListsFromArray returns a list of added entries and a list of removal entries +func AddedAndRemovalListsFromArray(m []string) ([]string, []string) { + stringToRemove := []string{} + stringToAdd := []string{} + for _, key := range m { + if strings.HasSuffix(key, "-") { + stringToRemove = append(stringToRemove, key[:len(key)-1]) + } else { + stringToAdd = append(stringToAdd, key) + } + } + return stringToAdd, stringToRemove +} + +// ToTrackerReference will parse a subject in form of kind:apiVersion:name for +// named resources or kind:apiVersion:labelKey1=value1,labelKey2=value2 for +// matching via a label selector. +func ToTrackerReference(subject, namespace string) (*tracker.Reference, error) { + parts := strings.SplitN(subject, ":", 3) + if len(parts) < 3 { + return nil, fmt.Errorf("invalid subject argument '%s': not in format kind:api/version:nameOrSelector", subject) + } + kind := parts[0] + gv, err := schema.ParseGroupVersion(parts[1]) + if err != nil { + return nil, err + } + reference := &tracker.Reference{ + APIVersion: gv.String(), + Kind: kind, + Namespace: namespace, + } + if !strings.Contains(parts[2], "=") { + reference.Name = parts[2] + } else { + selector, err := ParseSelector(parts[2]) + if err != nil { + return nil, err + } + reference.Selector = &metav1.LabelSelector{MatchLabels: selector} + } + return reference, nil +} + +// ParseSelector will parse a label selector in form of labelKey1=value1,labelKey2=value2. +func ParseSelector(labelSelector string) (map[string]string, error) { + selector := map[string]string{} + for _, p := range strings.Split(labelSelector, ",") { + keyValue := strings.SplitN(p, "=", 2) + if len(keyValue) != 2 { + return nil, fmt.Errorf("invalid subject label selector '%s', expected format: key1=value,key2=value", labelSelector) + } + selector[keyValue[0]] = keyValue[1] + } + return selector, nil +} + +// mapFromArray takes an array of strings where each item is a (key, value) pair +// separated by a delimiter and returns a map where keys are mapped to their respective values. +// If allowSingles is true, values without a delimiter will be added as keys pointing to empty strings +func mapFromArray(arr []string, delimiter string, allowSingles bool) (map[string]string, error) { + if len(arr) == 0 { + return nil, nil + } + + returnMap := map[string]string{} + for _, pairStr := range arr { + pairSlice := strings.SplitN(pairStr, delimiter, 2) + if len(pairSlice) <= 1 { + if len(pairSlice) == 0 || !allowSingles { + return nil, fmt.Errorf("Argument requires a value that contains the %q character; got %q", delimiter, pairStr) + } + returnMap[pairSlice[0]] = "" + } else { + if pairSlice[0] == "" { + return nil, fmt.Errorf("The key is empty") + } + if _, ok := returnMap[pairSlice[0]]; ok { + return nil, fmt.Errorf("The key %q has been duplicate in %v", pairSlice[0], arr) + } + returnMap[pairSlice[0]] = pairSlice[1] + } + } + return returnMap, nil +} diff --git a/vendor/knative.dev/client-pkg/pkg/util/schema_handling.go b/vendor/knative.dev/client-pkg/pkg/util/schema_handling.go new file mode 100644 index 0000000000..8291f6bb9d --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/util/schema_handling.go @@ -0,0 +1,44 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package util + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func UpdateGroupVersionKindWithScheme(obj runtime.Object, gv schema.GroupVersion, scheme *runtime.Scheme) error { + gvk, err := GetGroupVersionKind(obj, gv, scheme) + if err != nil { + return err + } + obj.GetObjectKind().SetGroupVersionKind(*gvk) + return nil +} + +func GetGroupVersionKind(obj runtime.Object, gv schema.GroupVersion, scheme *runtime.Scheme) (*schema.GroupVersionKind, error) { + gvks, _, err := scheme.ObjectKinds(obj) + if err != nil { + return nil, err + } + for _, gvk := range gvks { + if gvk.GroupVersion() == gv { + return &gvk, nil + } + } + return nil, fmt.Errorf("no group version %s registered in %s", gv, scheme.Name()) +} diff --git a/vendor/knative.dev/client-pkg/pkg/util/unstructured.go b/vendor/knative.dev/client-pkg/pkg/util/unstructured.go new file mode 100644 index 0000000000..492b8b3f24 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/util/unstructured.go @@ -0,0 +1,66 @@ +// 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 util + +import ( + "encoding/json" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" +) + +// ToUnstructuredList is to convert an object to unstructured.UnstructuredList. +// If the object is not a list type, it will convert to a single item UnstructuredList. +func ToUnstructuredList(obj runtime.Object) (*unstructured.UnstructuredList, error) { + unstructuredList := &unstructured.UnstructuredList{} + + if meta.IsListType(obj) { + unstructuredList.SetGroupVersionKind(obj.GetObjectKind().GroupVersionKind()) + + items, err := meta.ExtractList(obj) + if err != nil { + return nil, err + } + for _, obji := range items { + ud, err := ToUnstructured(obji) + if err != nil { + return nil, err + } + unstructuredList.Items = append(unstructuredList.Items, *ud) + } + + } else { + ud, err := ToUnstructured(obj) + if err != nil { + return nil, err + } + unstructuredList.Items = append(unstructuredList.Items, *ud) + } + return unstructuredList, nil + +} + +func ToUnstructured(obj runtime.Object) (*unstructured.Unstructured, error) { + b, err := json.Marshal(obj) + if err != nil { + return nil, err + } + ud := &unstructured.Unstructured{} + if err := json.Unmarshal(b, ud); err != nil { + return nil, err + } + return ud, nil +} diff --git a/vendor/knative.dev/client-pkg/pkg/wait/poll_watcher.go b/vendor/knative.dev/client-pkg/pkg/wait/poll_watcher.go new file mode 100644 index 0000000000..c88950b8ac --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/wait/poll_watcher.go @@ -0,0 +1,189 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wait + +import ( + "context" + "sync" + "time" + + api_errors "k8s.io/apimachinery/pkg/api/errors" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/rest" +) + +const pollInterval = time.Second + +// PollInterval determines when you should poll. Useful to mock out, or for +// replacing with exponential backoff later. +type PollInterval interface { + PollChan() <-chan time.Time + Stop() +} + +type pollingWatcher struct { + c rest.Interface + ns string + resource string + name string + timeout time.Duration + done chan bool + result chan watch.Event + wg *sync.WaitGroup + // we can mock the interface for testing. + pollInterval PollInterval + // mock hook for testing. + poll func() (runtime.Object, error) +} + +type watchF func(context.Context, v1.ListOptions) (watch.Interface, error) + +type tickerPollInterval struct { + t *time.Ticker +} + +func (t *tickerPollInterval) PollChan() <-chan time.Time { + return t.t.C +} + +func (t *tickerPollInterval) Stop() { + t.t.Stop() +} + +func newTickerPollInterval(d time.Duration) *tickerPollInterval { + return &tickerPollInterval{time.NewTicker(d)} +} + +// NewWatcherWithVersion makes a watch.Interface on the given resource in the client, +// falling back to polling if the server does not support Watch. +func NewWatcherWithVersion(ctx context.Context, watchFunc watchF, c rest.Interface, ns string, resource string, name string, initialResourceVersion string, timeout time.Duration) (watch.Interface, error) { + native, err := nativeWatchWithVersion(ctx, watchFunc, name, initialResourceVersion, timeout) + if err == nil { + return native, nil + } + polling := &pollingWatcher{ + c, ns, resource, name, timeout, make(chan bool), make(chan watch.Event), &sync.WaitGroup{}, + newTickerPollInterval(time.Second), nativePoll(ctx, c, ns, resource, name)} + polling.start() + return polling, nil +} + +func (w *pollingWatcher) start() { + w.wg.Add(1) + + go func() { + defer w.wg.Done() + defer w.pollInterval.Stop() + var err error + var old, new runtime.Object + done := false + for !done { + old = new + + select { + case <-w.pollInterval.PollChan(): + new, err = w.poll() + newObj, ok1 := new.(v1.Object) + oldObj, ok2 := old.(v1.Object) + + if err != nil && api_errors.IsNotFound(err) { + if old != nil { + // Deleted + w.result <- watch.Event{ + Type: watch.Deleted, + Object: old, + } + } + //... Otherwise maybe just doesn't exist. + } else if err != nil { + // Just an error + w.result <- watch.Event{ + Type: watch.Error, + } + } else if old == nil && new != nil { + // Added + w.result <- watch.Event{ + Type: watch.Added, + Object: new, + } + } else if !(ok1 && ok2) { + // Error wrong types + w.result <- watch.Event{ + Type: watch.Error, + } + } else if newObj.GetUID() != oldObj.GetUID() { + // Deleted and readded. + w.result <- watch.Event{ + Type: watch.Deleted, + Object: old, + } + w.result <- watch.Event{ + Type: watch.Added, + Object: new, + } + } else if newObj.GetResourceVersion() != oldObj.GetResourceVersion() { + // Modified. + w.result <- watch.Event{ + Type: watch.Modified, + Object: new, + } + } + case done = <-w.done: + break + } + } + }() +} + +func (w *pollingWatcher) ResultChan() <-chan watch.Event { + return w.result +} + +func (w *pollingWatcher) Stop() { + w.done <- true + w.wg.Wait() + close(w.result) + close(w.done) +} + +func nativeWatchWithVersion(ctx context.Context, watchFunc watchF, name string, initialVersion string, timeout time.Duration) (watch.Interface, error) { + opts := v1.ListOptions{ + ResourceVersion: initialVersion, + FieldSelector: fields.OneTermEqualSelector("metadata.name", name).String(), + } + opts.Watch = true + addWatchTimeout(&opts, timeout) + return watchFunc(ctx, opts) +} + +func nativePoll(ctx context.Context, c rest.Interface, ns, resource, name string) func() (runtime.Object, error) { + return func() (runtime.Object, error) { + return c.Get().Namespace(ns).Resource(resource).Name(name).Do(ctx).Get() + } +} + +func addWatchTimeout(opts *v1.ListOptions, timeout time.Duration) { + if timeout == 0 { + return + } + // Wait for service to enter 'Ready' state, with a timeout of which is slightly larger than + // the provided timeout. We have our own timeout which fires after "timeout" seconds + // and stops the watch + timeOutWatchSeconds := int64((timeout + 30*time.Second) / time.Second) + opts.TimeoutSeconds = &timeOutWatchSeconds +} diff --git a/vendor/knative.dev/client-pkg/pkg/wait/test_wait_helper.go b/vendor/knative.dev/client-pkg/pkg/wait/test_wait_helper.go new file mode 100644 index 0000000000..fe2b6da4af --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/wait/test_wait_helper.go @@ -0,0 +1,87 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wait + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/watch" + "knative.dev/pkg/apis" + servingv1 "knative.dev/serving/pkg/apis/serving/v1" +) + +// Helper for testing watch functionality +type FakeWatch struct { + eventChan chan watch.Event + events []watch.Event + + // Record how often stop was called + StopCalled int +} + +// Create a new fake watch with the given events which will be send when +// on start +func NewFakeWatch(events []watch.Event) *FakeWatch { + return &FakeWatch{ + eventChan: make(chan watch.Event), + events: events, + } +} + +// Stop the watch channel +func (f *FakeWatch) Stop() { + f.StopCalled++ +} + +// Start and fire events +func (f *FakeWatch) Start() { + go f.fireEvents() +} + +// Channel for getting the events +func (f *FakeWatch) ResultChan() <-chan watch.Event { + return f.eventChan +} + +func (f *FakeWatch) fireEvents() { + for _, ev := range f.events { + f.eventChan <- ev + } +} + +// CreateTestServiceWithConditions create a service skeleton with a given +// ConditionReady status and all other statuses set to otherReadyStatus. +// Optionally a single generation can be added. +func CreateTestServiceWithConditions( + name string, + readyStatus, otherReadyStatus corev1.ConditionStatus, + reason, message string, + generations ...int64, +) *servingv1.Service { + service := servingv1.Service{ObjectMeta: metav1.ObjectMeta{Name: name}} + if len(generations) == 2 { + service.Generation = generations[0] + service.Status.ObservedGeneration = generations[1] + } else { + service.Generation = 1 + service.Status.ObservedGeneration = 1 + } + service.Status.Conditions = []apis.Condition{ + {Type: "RoutesReady", Status: otherReadyStatus}, + {Type: apis.ConditionReady, Status: readyStatus, Reason: reason, Message: message}, + {Type: "ConfigurationsReady", Status: otherReadyStatus}, + } + return &service +} diff --git a/vendor/knative.dev/client-pkg/pkg/wait/wait_for_ready.go b/vendor/knative.dev/client-pkg/pkg/wait/wait_for_ready.go new file mode 100644 index 0000000000..381c372a82 --- /dev/null +++ b/vendor/knative.dev/client-pkg/pkg/wait/wait_for_ready.go @@ -0,0 +1,312 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wait + +import ( + "context" + "fmt" + "io" + "time" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "knative.dev/pkg/apis" +) + +// Callbacks and configuration used while waiting +type waitForReadyConfig struct { + watchMaker WatchMaker + conditionsExtractor ConditionsExtractor + kind string +} + +// Callbacks and configuration used while waiting for event +type waitForEvent struct { + watchMaker WatchMaker + eventDone EventDone + kind string +} + +// EventDone is a marker to stop actual waiting on given event state +type EventDone func(ev *watch.Event) bool + +// Interface used for waiting of a resource of a given name to reach a definitive +// state in its "Ready" condition. +type Wait interface { + + // Wait on resource the resource with this name + // and write event messages for unknown event to the status writer. + // Returns an error (if any) and the overall time it took to wait + Wait(ctx context.Context, name string, initialVersion string, options Options, msgCallback MessageCallback) (error, time.Duration) +} + +type Options struct { + // Window for how long a ReadyCondition == false has to stay + // for being considered as an error (useful for flaky reconciliation + ErrorWindow *time.Duration + + // Timeout for how long to wait at maximum + Timeout *time.Duration +} + +// Create watch which is used when waiting for Ready condition +type WatchMaker func(ctx context.Context, name string, initialVersion string, timeout time.Duration) (watch.Interface, error) + +// Extract conditions from a runtime object +type ConditionsExtractor func(obj runtime.Object) (apis.Conditions, error) + +// Callback for event messages +type MessageCallback func(durationSinceState time.Duration, message string) + +// NewWaitForReady waits until the condition is set to Ready == True +func NewWaitForReady(kind string, watchMaker WatchMaker, extractor ConditionsExtractor) Wait { + return &waitForReadyConfig{ + kind: kind, + watchMaker: watchMaker, + conditionsExtractor: extractor, + } +} + +// NewWaitForEvent creates a Wait object which waits until a specific event (i.e. when +// the EventDone function returns true) +func NewWaitForEvent(kind string, watchMaker WatchMaker, eventDone EventDone) Wait { + return &waitForEvent{ + kind: kind, + watchMaker: watchMaker, + eventDone: eventDone, + } +} + +// SimpleMessageCallback returns a callback which prints out a simple event message to a given writer +func SimpleMessageCallback(out io.Writer) MessageCallback { + oldMessage := "" + return func(duration time.Duration, message string) { + txt := message + if message == oldMessage { + txt = "..." + } + fmt.Fprintf(out, "%7.3fs %s\n", float64(duration.Round(time.Millisecond))/float64(time.Second), txt) + oldMessage = message + } +} + +// NoopMessageCallback is callback which does nothing +func NoopMessageCallback() MessageCallback { + return func(durationSinceState time.Duration, message string) {} +} + +// Wait until a resource enters condition of type "Ready" to "False" or "True". +// `watchFunc` creates the actual watch, `kind` is the type what your are watching for +// (e.g. "service"), `timeout` is a timeout after which the watch should be cancelled if no +// target state has been entered yet and `out` is used for printing out status messages +// msgCallback gets called for every event with an 'Ready' condition == UNKNOWN with the event's message. +func (w *waitForReadyConfig) Wait(ctx context.Context, name string, initialVersion string, options Options, msgCallback MessageCallback) (error, time.Duration) { + timeout := options.timeoutWithDefault() + timeoutTimer := time.NewTimer(timeout) + defer timeoutTimer.Stop() + for { + start := time.Now() + retry, timeoutReached, err := w.waitForReadyCondition(ctx, name, initialVersion, start, timeoutTimer, options.errorWindowWithDefault(), options, msgCallback) + + if err != nil { + return err, time.Since(start) + } + if timeoutReached { + return fmt.Errorf("timeout: %s '%s' not ready after %d seconds", w.kind, name, int(timeout/time.Second)), time.Since(start) + } + + if retry { + // sleep to prevent CPU pegging and restart the loop + time.Sleep(pollInterval) + continue + } + return nil, time.Since(start) + } +} + +// waitForReadyCondition waits until the status condition "Ready" is set to true (good path) or return an error +// when the "Ready" condition is set to false. An error is also returned when the given timeout is reached (plus the +// return value of timeoutReached is set to true in this case). +// An errorWindow can be specified which takes into account of intermediate "false" ready conditions. So before returning +// an error, this methods waits for the errorWindow duration and if an "True" or "Unknown" event arrives in the meantime +// for the "Ready" condition, then the method continues to wait. +func (w *waitForReadyConfig) waitForReadyCondition(ctx context.Context, name string, initialVersion string, start time.Time, + timeoutTimer *time.Timer, errorWindow time.Duration, options Options, msgCallback MessageCallback) (retry bool, timeoutReached bool, err error) { + + watcher, err := w.watchMaker(ctx, name, initialVersion, options.timeoutWithDefault()) + if err != nil { + return false, false, err + } + defer watcher.Stop() + // channel used to transport the error that has been received + errChan := make(chan error) + + var errorTimer *time.Timer + // Stop error timer if it has been started because of + // a ConditionReady has been set to false + defer (func() { + if errorTimer != nil { + errorTimer.Stop() + errorTimer = nil + } + })() + + for { + select { + case <-ctx.Done(): + return false, false, ctx.Err() + case <-timeoutTimer.C: + // We reached a timeout without receiving a "Ready" == "True" event + return false, true, nil + case err = <-errChan: + // The error timer fired and we have not received a recovery event ("True" / "Unknown") in the + // meantime. So the error status is considered to be final. + return false, false, err + case event, ok := <-watcher.ResultChan(): + if !ok || event.Object == nil { + return true, false, nil + } + + // Skip event if its not a MODIFIED event, as only MODIFIED events update the condition + // we are looking for. + // This will filter out all synthetic ADDED events that created bt the API server for + // the initial state. See https://kubernetes.io/docs/reference/using-api/api-concepts/#the-resourceversion-parameter + // for details: + // "Get State and Start at Most Recent: Start a watch at the most recent resource version, + // which must be consistent (i.e. served from etcd via a quorum read). To establish initial state, + // the watch begins with synthetic “Added” events of all resources instances that exist at the starting + // resource version. All following watch events are for all changes that occurred after the resource + // version the watch started at." + if event.Type != watch.Modified { + continue + } + + // Check whether resource is in sync already (meta.generation == status.observedGeneration) + inSync, err := generationCheck(event.Object) + if err != nil { + return false, false, err + } + + // Skip events if generations has not yet been consolidated, regardless of type. + // Wait for the next event to come in until the generations align + if !inSync { + continue + } + + conditions, err := w.conditionsExtractor(event.Object) + if err != nil { + return false, false, err + } + for _, cond := range conditions { + if cond.Type == apis.ConditionReady { + switch cond.Status { + case corev1.ConditionTrue: + // Any error timer running will be cancelled by the defer method that has been set above + return false, false, nil + case corev1.ConditionFalse: + // Fire up a timer waiting for the error window duration to still allow to reconcile + // to a true condition even after the condition went to false. If this is not the case within + // this window, then an error is returned. + // If there is already a timer running, we just log. + if errorTimer == nil { + err := fmt.Errorf("%s: %s", cond.Reason, cond.Message) + errorTimer = time.AfterFunc(errorWindow, func() { + errChan <- err + }) + } + case corev1.ConditionUnknown: + // If an errorTimer is triggered because of a previous "False" event, but now + // we received an "Unknown" event during the error window, cancel the error timer + // to avoid to receive an error signal. + if errorTimer != nil { + errorTimer.Stop() + errorTimer = nil + } + } + if cond.Message != "" { + msgCallback(time.Since(start), cond.Message) + } + } + } + } + } +} + +// Wait until the expected EventDone is satisfied +func (w *waitForEvent) Wait(ctx context.Context, name string, initialVersion string, options Options, msgCallback MessageCallback) (error, time.Duration) { + watcher, err := w.watchMaker(ctx, name, initialVersion, options.timeoutWithDefault()) + if err != nil { + return err, 0 + } + defer watcher.Stop() + + timeout := options.timeoutWithDefault() + start := time.Now() + // channel used to transport the error + timer := time.NewTimer(timeout) + defer timer.Stop() + for { + select { + case <-ctx.Done(): + return ctx.Err(), time.Since(start) + case <-timer.C: + return fmt.Errorf("timeout: %s '%s' not ready after %d seconds", w.kind, name, int(timeout/time.Second)), time.Since(start) + case event := <-watcher.ResultChan(): + if w.eventDone(&event) { + return nil, time.Since(start) + } + } + } +} + +func generationCheck(object runtime.Object) (bool, error) { + unstructured, err := runtime.DefaultUnstructuredConverter.ToUnstructured(object) + if err != nil { + return false, err + } + meta, ok := unstructured["metadata"].(map[string]interface{}) + if !ok { + return false, fmt.Errorf("cannot extract metadata from %v", object) + } + status, ok := unstructured["status"].(map[string]interface{}) + if !ok { + return false, fmt.Errorf("cannot extract status from %v", object) + } + observedGeneration, ok := status["observedGeneration"] + if !ok { + // Can be the case if not status has been attached yet + return false, nil + } + givenGeneration, ok := meta["generation"] + if !ok { + return false, fmt.Errorf("no field 'generation' in metadata of %v", object) + } + return givenGeneration == observedGeneration, nil +} + +func (o Options) timeoutWithDefault() time.Duration { + if o.Timeout != nil { + return *o.Timeout + } + return 60 * time.Second +} + +func (o Options) errorWindowWithDefault() time.Duration { + if o.ErrorWindow != nil { + return *o.ErrorWindow + } + return 2 * time.Second +} diff --git a/vendor/knative.dev/eventing-kafka/LICENSE b/vendor/knative.dev/eventing-kafka/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/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. diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/register.go b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/register.go new file mode 100644 index 0000000000..fb66f124d9 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/register.go @@ -0,0 +1,33 @@ +/* +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 bindings contains bindings API versions +package bindings + +import "k8s.io/apimachinery/pkg/runtime/schema" + +const ( + // TODO(mattmoor): Consider creating this under knative.dev/pkg/apis/bindings? + GroupName = "bindings.knative.dev" +) + +var ( + // KafkaBindingsResource represents a KafkaBinding + KafkaBindingsResource = schema.GroupResource{ + Group: GroupName, + Resource: "kafkabindings", + } +) diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/doc.go b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/doc.go new file mode 100644 index 0000000000..e1c1c2c601 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/doc.go @@ -0,0 +1,22 @@ +/* +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 v1beta1 contains API Schema definitions for the sources v1beta1 API group +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register +// +k8s:defaulter-gen=TypeMeta +// +groupName=bindings.knative.dev +package v1beta1 diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/fuzzer.go b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/fuzzer.go new file mode 100644 index 0000000000..f6ff68a2ce --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/fuzzer.go @@ -0,0 +1,45 @@ +/* +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 v1beta1 + +import ( + fuzz "github.com/google/gofuzz" + "k8s.io/apimachinery/pkg/api/apitesting/fuzzer" + "k8s.io/apimachinery/pkg/runtime/serializer" + pkgfuzzer "knative.dev/pkg/apis/testing/fuzzer" +) + +// FuzzerFuncs includes fuzzing funcs for bindings.knative.dev v1beta1 types +// +// For other examples see +// https://github.com/kubernetes/apimachinery/blob/master/pkg/apis/meta/fuzzer/fuzzer.go +var FuzzerFuncs = fuzzer.MergeFuzzerFuncs( + func(codecs serializer.CodecFactory) []interface{} { + return []interface{}{ + func(s *KafkaBindingStatus, c fuzz.Continue) { + c.FuzzNoCustom(s) // fuzz the status object + + // Clear the random fuzzed condition + s.Status.SetConditions(nil) + + // Fuzz the known conditions except their type value + s.InitializeConditions() + pkgfuzzer.FuzzConditions(&s.Status, c) + }, + } + }, +) diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_conversion.go b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_conversion.go new file mode 100644 index 0000000000..4465370e05 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_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 v1beta1 + +import ( + "context" + "fmt" + + "knative.dev/pkg/apis" +) + +// ConvertTo implements apis.Convertible +func (source *KafkaBinding) ConvertTo(_ context.Context, sink apis.Convertible) error { + return fmt.Errorf("v1beta1 is the highest known version, got: %T", sink) +} + +// ConvertFrom implements apis.Convertible +func (sink *KafkaBinding) ConvertFrom(_ context.Context, source apis.Convertible) error { + return fmt.Errorf("v1beta1 is the highest known version, got: %T", source) +} + +// ConvertTo implements apis.Convertible +func (source *KafkaAuthSpec) ConvertTo(_ context.Context, sink apis.Convertible) error { + return fmt.Errorf("v1beta1 is the highest known version, got: %T", sink) +} + +// ConvertFrom implements apis.Convertible +func (sink *KafkaAuthSpec) ConvertFrom(_ context.Context, source apis.Convertible) error { + return fmt.Errorf("v1beta1 is the highest known version, got: %T", source) +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_defaults.go b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_defaults.go new file mode 100644 index 0000000000..2c2b16cd1d --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_defaults.go @@ -0,0 +1,29 @@ +/* +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 v1beta1 + +import ( + "context" +) + +// SetDefaults ensures KafkaBinding reflects the default values. +func (r *KafkaBinding) SetDefaults(ctx context.Context) { + if r.Spec.Subject.Namespace == "" { + // Default the subject's namespace to our namespace. + r.Spec.Subject.Namespace = r.Namespace + } +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_lifecycle.go b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_lifecycle.go new file mode 100644 index 0000000000..6e27e7fd47 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_lifecycle.go @@ -0,0 +1,225 @@ +/* +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 v1beta1 + +import ( + "context" + "strings" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "knative.dev/pkg/apis" + "knative.dev/pkg/apis/duck" + duckv1 "knative.dev/pkg/apis/duck/v1" + "knative.dev/pkg/tracker" +) + +var kfbCondSet = apis.NewLivingConditionSet() + +// GetGroupVersionKind returns the GroupVersionKind. +func (*KafkaBinding) GetGroupVersionKind() schema.GroupVersionKind { + return SchemeGroupVersion.WithKind("KafkaBinding") +} + +// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface. +func (*KafkaBinding) GetConditionSet() apis.ConditionSet { + return kfbCondSet +} + +// GetUntypedSpec implements apis.HasSpec +func (s *KafkaBinding) GetUntypedSpec() interface{} { + return s.Spec +} + +// GetSubject implements psbinding.Bindable +func (sb *KafkaBinding) GetSubject() tracker.Reference { + return sb.Spec.Subject +} + +// GetBindingStatus implements psbinding.Bindable +func (sb *KafkaBinding) GetBindingStatus() duck.BindableStatus { + return &sb.Status +} + +// SetObservedGeneration implements psbinding.BindableStatus +func (sbs *KafkaBindingStatus) SetObservedGeneration(gen int64) { + sbs.ObservedGeneration = gen +} + +// InitializeConditions populates the KafkaBindingStatus's conditions field +// with all of its conditions configured to Unknown. +func (sbs *KafkaBindingStatus) InitializeConditions() { + kfbCondSet.Manage(sbs).InitializeConditions() +} + +// MarkBindingUnavailable marks the KafkaBinding's Ready condition to False with +// the provided reason and message. +func (sbs *KafkaBindingStatus) MarkBindingUnavailable(reason, message string) { + kfbCondSet.Manage(sbs).MarkFalse(KafkaBindingConditionReady, reason, message) +} + +// MarkBindingAvailable marks the KafkaBinding's Ready condition to True. +func (sbs *KafkaBindingStatus) MarkBindingAvailable() { + kfbCondSet.Manage(sbs).MarkTrue(KafkaBindingConditionReady) +} + +// Do implements psbinding.Bindable +func (kfb *KafkaBinding) Do(ctx context.Context, ps *duckv1.WithPod) { + // First undo so that we can just unconditionally append below. + kfb.Undo(ctx, ps) + + spec := ps.Spec.Template.Spec + for i := range spec.InitContainers { + spec.InitContainers[i].Env = append(spec.InitContainers[i].Env, corev1.EnvVar{ + Name: "KAFKA_BOOTSTRAP_SERVERS", + Value: strings.Join(kfb.Spec.BootstrapServers, ","), + }) + if kfb.Spec.Net.SASL.Enable { + spec.InitContainers[i].Env = append(spec.InitContainers[i].Env, corev1.EnvVar{ + Name: "KAFKA_NET_SASL_ENABLE", + Value: "true", + }, corev1.EnvVar{ + Name: "KAFKA_NET_SASL_USER", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: kfb.Spec.Net.SASL.User.SecretKeyRef, + }, + }, corev1.EnvVar{ + Name: "KAFKA_NET_SASL_PASSWORD", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: kfb.Spec.Net.SASL.Password.SecretKeyRef, + }, + }, corev1.EnvVar{ + Name: "KAFKA_NET_SASL_TYPE", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: kfb.Spec.Net.SASL.Type.SecretKeyRef, + }, + }) + } + if kfb.Spec.Net.TLS.Enable { + spec.InitContainers[i].Env = append(spec.InitContainers[i].Env, corev1.EnvVar{ + Name: "KAFKA_NET_TLS_ENABLE", + Value: "true", + }, corev1.EnvVar{ + Name: "KAFKA_NET_TLS_CERT", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: kfb.Spec.Net.TLS.Cert.SecretKeyRef, + }, + }, corev1.EnvVar{ + Name: "KAFKA_NET_TLS_KEY", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: kfb.Spec.Net.TLS.Key.SecretKeyRef, + }, + }, corev1.EnvVar{ + Name: "KAFKA_NET_TLS_CA_CERT", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: kfb.Spec.Net.TLS.CACert.SecretKeyRef, + }, + }) + } + } + + for i := range spec.Containers { + spec.Containers[i].Env = append(spec.Containers[i].Env, corev1.EnvVar{ + Name: "KAFKA_BOOTSTRAP_SERVERS", + Value: strings.Join(kfb.Spec.BootstrapServers, ","), + }) + + if kfb.Spec.Net.SASL.Enable { + spec.Containers[i].Env = append(spec.Containers[i].Env, corev1.EnvVar{ + Name: "KAFKA_NET_SASL_ENABLE", + Value: "true", + }, corev1.EnvVar{ + Name: "KAFKA_NET_SASL_USER", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: kfb.Spec.Net.SASL.User.SecretKeyRef, + }, + }, corev1.EnvVar{ + Name: "KAFKA_NET_SASL_PASSWORD", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: kfb.Spec.Net.SASL.Password.SecretKeyRef, + }, + }, corev1.EnvVar{ + Name: "KAFKA_NET_SASL_TYPE", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: kfb.Spec.Net.SASL.Type.SecretKeyRef, + }, + }) + } + if kfb.Spec.Net.TLS.Enable { + spec.Containers[i].Env = append(spec.Containers[i].Env, corev1.EnvVar{ + Name: "KAFKA_NET_TLS_ENABLE", + Value: "true", + }, corev1.EnvVar{ + Name: "KAFKA_NET_TLS_CERT", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: kfb.Spec.Net.TLS.Cert.SecretKeyRef, + }, + }, corev1.EnvVar{ + Name: "KAFKA_NET_TLS_KEY", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: kfb.Spec.Net.TLS.Key.SecretKeyRef, + }, + }, corev1.EnvVar{ + Name: "KAFKA_NET_TLS_CA_CERT", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: kfb.Spec.Net.TLS.CACert.SecretKeyRef, + }, + }) + } + } +} + +func (kfb *KafkaBinding) Undo(ctx context.Context, ps *duckv1.WithPod) { + spec := ps.Spec.Template.Spec + + for i, c := range spec.InitContainers { + if len(c.Env) == 0 { + continue + } + env := make([]corev1.EnvVar, 0, len(spec.InitContainers[i].Env)) + for j, ev := range c.Env { + switch ev.Name { + case "KAFKA_NET_TLS_ENABLE", "KAFKA_NET_TLS_CERT", "KAFKA_NET_TLS_KEY", "KAFKA_NET_TLS_CA_CERT", + "KAFKA_NET_SASL_ENABLE", "KAFKA_NET_SASL_USER", "KAFKA_NET_SASL_PASSWORD", "KAFKA_NET_SASL_TYPE", + "KAFKA_BOOTSTRAP_SERVERS": + + continue + default: + env = append(env, spec.InitContainers[i].Env[j]) + } + } + spec.InitContainers[i].Env = env + } + + for i, c := range spec.Containers { + if len(c.Env) == 0 { + continue + } + env := make([]corev1.EnvVar, 0, len(spec.Containers[i].Env)) + for j, ev := range c.Env { + switch ev.Name { + case "KAFKA_NET_TLS_ENABLE", "KAFKA_NET_TLS_CERT", "KAFKA_NET_TLS_KEY", "KAFKA_NET_TLS_CA_CERT", + "KAFKA_NET_SASL_ENABLE", "KAFKA_NET_SASL_USER", "KAFKA_NET_SASL_PASSWORD", "KAFKA_NET_SASL_TYPE", + "KAFKA_BOOTSTRAP_SERVERS": + continue + default: + env = append(env, spec.Containers[i].Env[j]) + } + } + spec.Containers[i].Env = env + } +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_types.go b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_types.go new file mode 100644 index 0000000000..11b3289ed1 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_types.go @@ -0,0 +1,128 @@ +/* +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 v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" + duckv1alpha1 "knative.dev/pkg/apis/duck/v1alpha1" + "knative.dev/pkg/kmeta" + "knative.dev/pkg/webhook/resourcesemantics" +) + +// +genclient +// +genreconciler +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// KafkaBinding is the Schema for the kafkasources API. +// +k8s:openapi-gen=true +type KafkaBinding struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec KafkaBindingSpec `json:"spec,omitempty"` + Status KafkaBindingStatus `json:"status,omitempty"` +} + +// Check that KafkaBinding can be validated and can be defaulted. +var _ runtime.Object = (*KafkaBinding)(nil) +var _ resourcesemantics.GenericCRD = (*KafkaBinding)(nil) +var _ kmeta.OwnerRefable = (*KafkaBinding)(nil) +var _ duckv1.KRShaped = (*KafkaBinding)(nil) + +type KafkaSASLSpec struct { + Enable bool `json:"enable,omitempty"` + + // User is the Kubernetes secret containing the SASL username. + // +optional + User SecretValueFromSource `json:"user,omitempty"` + + // Password is the Kubernetes secret containing the SASL password. + // +optional + Password SecretValueFromSource `json:"password,omitempty"` + + // Type of saslType, defaults to plain (vs SCRAM-SHA-512 or SCRAM-SHA-256) + // +optional + Type SecretValueFromSource `json:"type,omitempty"` +} + +type KafkaTLSSpec struct { + Enable bool `json:"enable,omitempty"` + + // Cert is the Kubernetes secret containing the client certificate. + // +optional + Cert SecretValueFromSource `json:"cert,omitempty"` + // Key is the Kubernetes secret containing the client key. + // +optional + Key SecretValueFromSource `json:"key,omitempty"` + // CACert is the Kubernetes secret containing the server CA cert. + // +optional + CACert SecretValueFromSource `json:"caCert,omitempty"` +} + +// SecretValueFromSource represents the source of a secret value +type SecretValueFromSource struct { + // The Secret key to select from. + SecretKeyRef *corev1.SecretKeySelector `json:"secretKeyRef,omitempty"` +} + +type KafkaNetSpec struct { + SASL KafkaSASLSpec `json:"sasl,omitempty"` + TLS KafkaTLSSpec `json:"tls,omitempty"` +} + +type KafkaAuthSpec struct { + // Bootstrap servers are the Kafka servers the consumer will connect to. + // +required + BootstrapServers []string `json:"bootstrapServers"` + + Net KafkaNetSpec `json:"net,omitempty"` +} + +// KafkaBindingSpec defines the desired state of the KafkaBinding. +type KafkaBindingSpec struct { + duckv1alpha1.BindingSpec `json:",inline"` + + KafkaAuthSpec `json:",inline"` +} + +const ( + // KafkaBindingConditionReady is configured to indicate whether the Binding + // has been configured for resources subject to its runtime contract. + KafkaBindingConditionReady = apis.ConditionReady +) + +// KafkaBindingStatus defines the observed state of KafkaBinding. +type KafkaBindingStatus struct { + duckv1.Status `json:",inline"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// KafkaBindingList contains a list of KafkaBindings. +type KafkaBindingList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []KafkaBinding `json:"items"` +} + +// GetStatus retrieves the duck status for this resource. Implements the KRShaped interface. +func (k *KafkaBinding) GetStatus() *duckv1.Status { + return &k.Status.Status +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_validation.go b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_validation.go new file mode 100644 index 0000000000..84564567f0 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/kafka_validation.go @@ -0,0 +1,28 @@ +/* +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 v1beta1 + +import ( + "context" + + "knative.dev/pkg/apis" +) + +// Validate ensures KafkaBinding is properly configured. +func (r *KafkaBinding) Validate(ctx context.Context) *apis.FieldError { + return nil +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/register.go b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/register.go new file mode 100644 index 0000000000..6db41a11a1 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/register.go @@ -0,0 +1,60 @@ +/* +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. +*/ + +// NOTE: Boilerplate only. Ignore this file. + +// Package v1beta1 contains API Schema definitions for the sources v1beta1 API group +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register +// +k8s:defaulter-gen=TypeMeta +// +groupName=sources.knative.dev +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + + "knative.dev/eventing-kafka/pkg/apis/bindings" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: bindings.GroupName, Version: "v1beta1"} + +// 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, + &KafkaBinding{}, + &KafkaBindingList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/zz_generated.deepcopy.go b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..98d9c24125 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,222 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2021 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 v1beta1 + +import ( + v1 "k8s.io/api/core/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KafkaAuthSpec) DeepCopyInto(out *KafkaAuthSpec) { + *out = *in + if in.BootstrapServers != nil { + in, out := &in.BootstrapServers, &out.BootstrapServers + *out = make([]string, len(*in)) + copy(*out, *in) + } + in.Net.DeepCopyInto(&out.Net) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaAuthSpec. +func (in *KafkaAuthSpec) DeepCopy() *KafkaAuthSpec { + if in == nil { + return nil + } + out := new(KafkaAuthSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KafkaBinding) DeepCopyInto(out *KafkaBinding) { + *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 KafkaBinding. +func (in *KafkaBinding) DeepCopy() *KafkaBinding { + if in == nil { + return nil + } + out := new(KafkaBinding) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KafkaBinding) 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 *KafkaBindingList) DeepCopyInto(out *KafkaBindingList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]KafkaBinding, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaBindingList. +func (in *KafkaBindingList) DeepCopy() *KafkaBindingList { + if in == nil { + return nil + } + out := new(KafkaBindingList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KafkaBindingList) 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 *KafkaBindingSpec) DeepCopyInto(out *KafkaBindingSpec) { + *out = *in + in.BindingSpec.DeepCopyInto(&out.BindingSpec) + in.KafkaAuthSpec.DeepCopyInto(&out.KafkaAuthSpec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaBindingSpec. +func (in *KafkaBindingSpec) DeepCopy() *KafkaBindingSpec { + if in == nil { + return nil + } + out := new(KafkaBindingSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KafkaBindingStatus) DeepCopyInto(out *KafkaBindingStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaBindingStatus. +func (in *KafkaBindingStatus) DeepCopy() *KafkaBindingStatus { + if in == nil { + return nil + } + out := new(KafkaBindingStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KafkaNetSpec) DeepCopyInto(out *KafkaNetSpec) { + *out = *in + in.SASL.DeepCopyInto(&out.SASL) + in.TLS.DeepCopyInto(&out.TLS) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaNetSpec. +func (in *KafkaNetSpec) DeepCopy() *KafkaNetSpec { + if in == nil { + return nil + } + out := new(KafkaNetSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KafkaSASLSpec) DeepCopyInto(out *KafkaSASLSpec) { + *out = *in + in.User.DeepCopyInto(&out.User) + in.Password.DeepCopyInto(&out.Password) + in.Type.DeepCopyInto(&out.Type) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaSASLSpec. +func (in *KafkaSASLSpec) DeepCopy() *KafkaSASLSpec { + if in == nil { + return nil + } + out := new(KafkaSASLSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KafkaTLSSpec) DeepCopyInto(out *KafkaTLSSpec) { + *out = *in + in.Cert.DeepCopyInto(&out.Cert) + in.Key.DeepCopyInto(&out.Key) + in.CACert.DeepCopyInto(&out.CACert) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaTLSSpec. +func (in *KafkaTLSSpec) DeepCopy() *KafkaTLSSpec { + if in == nil { + return nil + } + out := new(KafkaTLSSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretValueFromSource) DeepCopyInto(out *SecretValueFromSource) { + *out = *in + if in.SecretKeyRef != nil { + in, out := &in.SecretKeyRef, &out.SecretKeyRef + *out = new(v1.SecretKeySelector) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretValueFromSource. +func (in *SecretValueFromSource) DeepCopy() *SecretValueFromSource { + if in == nil { + return nil + } + out := new(SecretValueFromSource) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/sources/config/doc.go b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/config/doc.go new file mode 100644 index 0000000000..a0d4319efc --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/config/doc.go @@ -0,0 +1,21 @@ +/* +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. +*/ + +// +k8s:deepcopy-gen=package + +// Package config holds the typed objects that define the schemas for +// ConfigMap objects that pertain to our API objects. +package config diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/sources/config/kafka_defaults.go b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/config/kafka_defaults.go new file mode 100644 index 0000000000..6602f66b76 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/config/kafka_defaults.go @@ -0,0 +1,143 @@ +/* +Copyright 2021 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 config + +import ( + "fmt" + "strconv" + + corev1 "k8s.io/api/core/v1" +) + +const ( + // KafkaDefaultsConfigName is the name of config map for the default + // configs that KafkaSource should use. + KafkaDefaultsConfigName = "config-kafka-source-defaults" + + // DefaultAutoscalingClassKey is the name of autoscaler class annotation + DefaultAutoscalingClassKey = "autoscalingClass" + + // DefaultMinScaleKey is the name of the key corresponding to the KEDA minScale annotation + DefaultMinScaleKey = "minScale" + + // DefaultMaxScaleKey is the name of the KEDA maxScale annotation + DefaultMaxScaleKey = "maxScale" + + // DefaultPollingIntervalKey is the name of the KEDA pollingInterval annotation + DefaultPollingIntervalKey = "pollingInterval" + + // DefaultCooldownPeriodKey is the name of the KEDA cooldownPeriod annotation + DefaultCooldownPeriodKey = "cooldownPeriod" + + // DefaultKafkaLagThresholdKey is the name of the KEDA kafkaLagThreshold annotation + DefaultKafkaLagThresholdKey = "kafkaLagThreshold" + + // KedaAutoscalingClass is the class name for KEDA + KedaAutoscalingClass = "keda.autoscaling.knative.dev" + + // DefaultMinScaleValue is the default value for DefaultMinScaleKey + DefaultMinScaleValue = int64(1) + + // DefaultMaxScaleValue is the default value for DefaultMaxScaleKey + DefaultMaxScaleValue = int64(1) + + // DefaultPollingIntervalValue is the default value for DefaultPollingIntervalKey + DefaultPollingIntervalValue = int64(30) + + // DefaultCooldownPeriodValue is the default value for DefaultCooldownPeriodKey + DefaultCooldownPeriodValue = int64(300) + + // DefaultKafkaLagThresholdValue is the default value for DefaultKafkaLagThresholdKey + DefaultKafkaLagThresholdValue = int64(10) +) + +// NewKafkaDefaultsConfigFromMap creates a KafkaSourceDefaults from the supplied Map +func NewKafkaDefaultsConfigFromMap(data map[string]string) (*KafkaSourceDefaults, error) { + nc := &KafkaSourceDefaults{} + + value, present := data[DefaultAutoscalingClassKey] + if !present || value == "" { + return nc, nil + } + if value != "keda.autoscaling.knative.dev" { + return nil, fmt.Errorf("invalid value %q for %s. Only keda.autoscaling.knative.dev is allowed", value, DefaultAutoscalingClassKey) + } + nc.AutoscalingClass = value + + int64Value, err := parseInt64Entry(data, DefaultMinScaleKey, DefaultMinScaleValue) + if err != nil { + return nil, err + } + nc.MinScale = int64Value + + int64Value, err = parseInt64Entry(data, DefaultMaxScaleKey, DefaultMaxScaleValue) + if err != nil { + return nil, err + } + nc.MaxScale = int64Value + + int64Value, err = parseInt64Entry(data, DefaultPollingIntervalKey, DefaultPollingIntervalValue) + if err != nil { + return nil, err + } + nc.PollingInterval = int64Value + + int64Value, err = parseInt64Entry(data, DefaultCooldownPeriodKey, DefaultCooldownPeriodValue) + if err != nil { + return nil, err + } + nc.CooldownPeriod = int64Value + + int64Value, err = parseInt64Entry(data, DefaultKafkaLagThresholdKey, DefaultKafkaLagThresholdValue) + if err != nil { + return nil, err + } + nc.KafkaLagThreshold = int64Value + + return nc, nil +} + +// NewKafkaDefaultsConfigFromConfigMap creates a KafkaSourceDefaults from the supplied configMap +func NewKafkaDefaultsConfigFromConfigMap(config *corev1.ConfigMap) (*KafkaSourceDefaults, error) { + return NewKafkaDefaultsConfigFromMap(config.Data) +} + +type KafkaSourceDefaults struct { + AutoscalingClass string `json:"autoscalingClass,omitempty"` + MinScale int64 `json:"minScale,omitempty"` + MaxScale int64 `json:"maxScale,omitempty"` + PollingInterval int64 `json:"pollingInterval,omitempty"` + CooldownPeriod int64 `json:"cooldownPeriod,omitempty"` + KafkaLagThreshold int64 `json:"kafkaLagThreshold,omitempty"` +} + +func (d *KafkaSourceDefaults) DeepCopy() *KafkaSourceDefaults { + if d == nil { + return nil + } + out := new(KafkaSourceDefaults) + *out = *d + return out +} + +func parseInt64Entry(data map[string]string, key string, defaults int64) (int64, error) { + value, present := data[key] + if !present { + return defaults, nil + } + return strconv.ParseInt(value, 0, 64) +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/sources/config/store.go b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/config/store.go new file mode 100644 index 0000000000..db796f0a72 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/config/store.go @@ -0,0 +1,97 @@ +/* +Copyright 2021 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 config + +import ( + "context" + + "knative.dev/pkg/configmap" +) + +type kafkaCfgKey struct{} + +// Config holds the collection of configurations that we attach to contexts. +// +k8s:deepcopy-gen=false +type Config struct { + KafkaSourceDefaults *KafkaSourceDefaults +} + +// FromContext extracts a Config from the provided context. +func FromContext(ctx context.Context) *Config { + x, ok := ctx.Value(kafkaCfgKey{}).(*Config) + if ok { + return x + } + return nil +} + +// FromContextOrDefaults is like FromContext, but when no Config is attached it +// returns a Config populated with the defaults for each of the Config fields. +func FromContextOrDefaults(ctx context.Context) *Config { + if cfg := FromContext(ctx); cfg != nil { + return cfg + } + kafkaDefaults, err := NewKafkaDefaultsConfigFromMap(map[string]string{}) + if err != nil || kafkaDefaults == nil { + kafkaDefaults = &KafkaSourceDefaults{} + } + x := &Config{ + KafkaSourceDefaults: kafkaDefaults, + } + + return x +} + +// ToContext attaches the provided Config to the provided context, returning the +// new context with the Config attached. +func ToContext(ctx context.Context, c *Config) context.Context { + return context.WithValue(ctx, kafkaCfgKey{}, c) +} + +// Store is a typed wrapper around configmap.Untyped store to handle our configmaps. +// +k8s:deepcopy-gen=false +type Store struct { + *configmap.UntypedStore +} + +// NewStore creates a new store of Configs and optionally calls functions when ConfigMaps are updated. +func NewStore(logger configmap.Logger, onAfterStore ...func(name string, value interface{})) *Store { + store := &Store{ + UntypedStore: configmap.NewUntypedStore( + "kafkadefaults", + logger, + configmap.Constructors{ + KafkaDefaultsConfigName: NewKafkaDefaultsConfigFromConfigMap, + }, + onAfterStore..., + ), + } + + return store +} + +// ToContext attaches the current Config state to the provided context. +func (s *Store) ToContext(ctx context.Context) context.Context { + return ToContext(ctx, s.Load()) +} + +// Load creates a Config from the current config state of the Store. +func (s *Store) Load() *Config { + return &Config{ + KafkaSourceDefaults: s.UntypedLoad(KafkaDefaultsConfigName).(*KafkaSourceDefaults).DeepCopy(), + } +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/doc.go b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/doc.go new file mode 100644 index 0000000000..611e9caa92 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/doc.go @@ -0,0 +1,22 @@ +/* +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 v1beta1 contains API Schema definitions for the sources v1beta1 API group +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register +// +k8s:defaulter-gen=TypeMeta +// +groupName=sources.knative.dev +package v1beta1 diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/fuzzer.go b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/fuzzer.go new file mode 100644 index 0000000000..52b8cc35b4 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/fuzzer.go @@ -0,0 +1,45 @@ +/* +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 v1beta1 + +import ( + fuzz "github.com/google/gofuzz" + "k8s.io/apimachinery/pkg/api/apitesting/fuzzer" + "k8s.io/apimachinery/pkg/runtime/serializer" + pkgfuzzer "knative.dev/pkg/apis/testing/fuzzer" +) + +// FuzzerFuncs includes fuzzing funcs for sources.knative.dev v1beta1 types +// +// For other examples see +// https://github.com/kubernetes/apimachinery/blob/master/pkg/apis/meta/fuzzer/fuzzer.go +var FuzzerFuncs = fuzzer.MergeFuzzerFuncs( + func(codecs serializer.CodecFactory) []interface{} { + return []interface{}{ + func(s *KafkaSourceStatus, c fuzz.Continue) { + c.FuzzNoCustom(s) // fuzz the status object + + // Clear the random fuzzed condition + s.Status.SetConditions(nil) + + // Fuzz the known conditions except their type value + s.InitializeConditions() + pkgfuzzer.FuzzConditions(&s.Status, c) + }, + } + }, +) diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_conversion.go b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_conversion.go new file mode 100644 index 0000000000..7f01a80608 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_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 v1beta1 + +import ( + "context" + "fmt" + + "knative.dev/pkg/apis" +) + +// ConvertTo implements apis.Convertible +func (source *KafkaSource) ConvertTo(ctx context.Context, sink apis.Convertible) error { + return fmt.Errorf("v1beta1 is the highest known version, got: %T", sink) +} + +// ConvertFrom implements apis.Convertible +func (sink *KafkaSource) ConvertFrom(ctx context.Context, source apis.Convertible) error { + return fmt.Errorf("v1beta1 is the highest known version, got: %T", source) +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_defaults.go b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_defaults.go new file mode 100644 index 0000000000..657365836f --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_defaults.go @@ -0,0 +1,74 @@ +/* +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 v1beta1 + +import ( + "context" + "strconv" + + "github.com/google/uuid" + "k8s.io/utils/pointer" + "knative.dev/pkg/apis" + + "knative.dev/eventing-kafka/pkg/apis/sources/config" +) + +const ( + uuidPrefix = "knative-kafka-source-" + + classAnnotation = "autoscaling.knative.dev/class" + minScaleAnnotation = "autoscaling.knative.dev/minScale" + maxScaleAnnotation = "autoscaling.knative.dev/maxScale" + pollingIntervalAnnotation = "keda.autoscaling.knative.dev/pollingInterval" + cooldownPeriodAnnotation = "keda.autoscaling.knative.dev/cooldownPeriod" + kafkaLagThresholdAnnotation = "keda.autoscaling.knative.dev/kafkaLagThreshold" +) + +// SetDefaults ensures KafkaSource reflects the default values. +func (k *KafkaSource) SetDefaults(ctx context.Context) { + ctx = apis.WithinParent(ctx, k.ObjectMeta) + + if k.Spec.ConsumerGroup == "" { + k.Spec.ConsumerGroup = uuidPrefix + uuid.New().String() + } + + if k.Spec.Consumers == nil { + k.Spec.Consumers = pointer.Int32(1) + } + + if k.Spec.InitialOffset == "" { + k.Spec.InitialOffset = OffsetLatest + } + + kafkaConfig := config.FromContextOrDefaults(ctx) + kafkaDefaults := kafkaConfig.KafkaSourceDefaults + if kafkaDefaults.AutoscalingClass == config.KedaAutoscalingClass { + if k.Annotations == nil { + k.Annotations = map[string]string{} + } + k.Annotations[classAnnotation] = kafkaDefaults.AutoscalingClass + + // Set all annotations regardless of defaults + k.Annotations[minScaleAnnotation] = strconv.FormatInt(kafkaDefaults.MinScale, 10) + k.Annotations[maxScaleAnnotation] = strconv.FormatInt(kafkaDefaults.MaxScale, 10) + k.Annotations[pollingIntervalAnnotation] = strconv.FormatInt(kafkaDefaults.PollingInterval, 10) + k.Annotations[cooldownPeriodAnnotation] = strconv.FormatInt(kafkaDefaults.CooldownPeriod, 10) + k.Annotations[kafkaLagThresholdAnnotation] = strconv.FormatInt(kafkaDefaults.KafkaLagThreshold, 10) + } + + k.Spec.Sink.SetDefaults(ctx) +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_lifecycle.go b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_lifecycle.go new file mode 100644 index 0000000000..43b0b6047c --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_lifecycle.go @@ -0,0 +1,163 @@ +/* +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 v1beta1 + +import ( + "sync" + + appsv1 "k8s.io/api/apps/v1" + "knative.dev/eventing/pkg/apis/duck" + "knative.dev/pkg/apis" +) + +const ( + // KafkaConditionReady has status True when the KafkaSource is ready to send events. + KafkaConditionReady = apis.ConditionReady + + // KafkaConditionSinkProvided has status True when the KafkaSource has been configured with a sink target. + KafkaConditionSinkProvided apis.ConditionType = "SinkProvided" + + // KafkaConditionDeployed has status True when the KafkaSource has had it's receive adapter deployment created. + KafkaConditionDeployed apis.ConditionType = "Deployed" + + // KafkaConditionKeyType is True when the KafkaSource has been configured with valid key type for + // the key deserializer. + KafkaConditionKeyType apis.ConditionType = "KeyTypeCorrect" + + // KafkaConditionConfigReady has status True when the Kafka configuration to use by the source + // succeeded in establishing a connection to Kafka. + KafkaConditionConnectionEstablished apis.ConditionType = "ConnectionEstablished" + + // KafkaConditionInitialOffsetsCommitted is True when the KafkaSource has committed the + // initial offset of all claims + KafkaConditionInitialOffsetsCommitted apis.ConditionType = "InitialOffsetsCommitted" +) + +var ( + KafkaSourceCondSet = apis.NewLivingConditionSet( + KafkaConditionSinkProvided, + KafkaConditionDeployed, + KafkaConditionConnectionEstablished, + KafkaConditionInitialOffsetsCommitted, + ) + + kafkaCondSetLock = sync.RWMutex{} +) + +// RegisterAlternateKafkaConditionSet register an alternate apis.ConditionSet. +func RegisterAlternateKafkaConditionSet(conditionSet apis.ConditionSet) { + kafkaCondSetLock.Lock() + defer kafkaCondSetLock.Unlock() + + KafkaSourceCondSet = conditionSet +} + +// GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface. +func (*KafkaSource) GetConditionSet() apis.ConditionSet { + return KafkaSourceCondSet +} + +func (s *KafkaSourceStatus) GetCondition(t apis.ConditionType) *apis.Condition { + return KafkaSourceCondSet.Manage(s).GetCondition(t) +} + +// IsReady returns true if the resource is ready overall. +func (s *KafkaSourceStatus) IsReady() bool { + return KafkaSourceCondSet.Manage(s).IsHappy() +} + +// InitializeConditions sets relevant unset conditions to Unknown state. +func (s *KafkaSourceStatus) InitializeConditions() { + KafkaSourceCondSet.Manage(s).InitializeConditions() +} + +// MarkSink sets the condition that the source has a sink configured. +func (s *KafkaSourceStatus) MarkSink(uri *apis.URL) { + s.SinkURI = uri + if !uri.IsEmpty() { + KafkaSourceCondSet.Manage(s).MarkTrue(KafkaConditionSinkProvided) + } else { + KafkaSourceCondSet.Manage(s).MarkUnknown(KafkaConditionSinkProvided, "SinkEmpty", "Sink has resolved to empty.%s", "") + } +} + +// MarkNoSink sets the condition that the source does not have a sink configured. +func (s *KafkaSourceStatus) MarkNoSink(reason, messageFormat string, messageA ...interface{}) { + KafkaSourceCondSet.Manage(s).MarkFalse(KafkaConditionSinkProvided, reason, messageFormat, messageA...) +} + +func DeploymentIsAvailable(d *appsv1.DeploymentStatus, def bool) bool { + // Check if the Deployment is available. + for _, cond := range d.Conditions { + if cond.Type == appsv1.DeploymentAvailable { + return cond.Status == "True" + } + } + return def +} + +// MarkDeployed sets the condition that the source has been deployed. +func (s *KafkaSourceStatus) MarkDeployed(d *appsv1.Deployment) { + if duck.DeploymentIsAvailable(&d.Status, false) { + KafkaSourceCondSet.Manage(s).MarkTrue(KafkaConditionDeployed) + + // Propagate the number of consumers + s.Consumers = d.Status.Replicas + } else { + // I don't know how to propagate the status well, so just give the name of the Deployment + // for now. + KafkaSourceCondSet.Manage(s).MarkFalse(KafkaConditionDeployed, "DeploymentUnavailable", "The Deployment '%s' is unavailable.", d.Name) + } +} + +// MarkDeploying sets the condition that the source is deploying. +func (s *KafkaSourceStatus) MarkDeploying(reason, messageFormat string, messageA ...interface{}) { + KafkaSourceCondSet.Manage(s).MarkUnknown(KafkaConditionDeployed, reason, messageFormat, messageA...) +} + +// MarkNotDeployed sets the condition that the source has not been deployed. +func (s *KafkaSourceStatus) MarkNotDeployed(reason, messageFormat string, messageA ...interface{}) { + KafkaSourceCondSet.Manage(s).MarkFalse(KafkaConditionDeployed, reason, messageFormat, messageA...) +} + +func (s *KafkaSourceStatus) MarkKeyTypeCorrect() { + KafkaSourceCondSet.Manage(s).MarkTrue(KafkaConditionKeyType) +} + +func (s *KafkaSourceStatus) MarkKeyTypeIncorrect(reason, messageFormat string, messageA ...interface{}) { + KafkaSourceCondSet.Manage(s).MarkFalse(KafkaConditionKeyType, reason, messageFormat, messageA...) +} + +func (cs *KafkaSourceStatus) MarkConnectionEstablished() { + KafkaSourceCondSet.Manage(cs).MarkTrue(KafkaConditionConnectionEstablished) +} + +func (cs *KafkaSourceStatus) MarkConnectionNotEstablished(reason, messageFormat string, messageA ...interface{}) { + KafkaSourceCondSet.Manage(cs).MarkFalse(KafkaConditionConnectionEstablished, reason, messageFormat, messageA...) +} + +func (s *KafkaSourceStatus) MarkInitialOffsetCommitted() { + KafkaSourceCondSet.Manage(s).MarkTrue(KafkaConditionInitialOffsetsCommitted) +} + +func (s *KafkaSourceStatus) MarkInitialOffsetNotCommitted(reason, messageFormat string, messageA ...interface{}) { + KafkaSourceCondSet.Manage(s).MarkFalse(KafkaConditionInitialOffsetsCommitted, reason, messageFormat, messageA...) +} + +func (s *KafkaSourceStatus) UpdateConsumerGroupStatus(status string) { + s.Claims = status +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_lifecycle_mt.go b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_lifecycle_mt.go new file mode 100644 index 0000000000..3dff04d2d5 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_lifecycle_mt.go @@ -0,0 +1,39 @@ +/* +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 v1beta1 + +import ( + "knative.dev/pkg/apis" +) + +const ( + + // KafkaConditionScheduled is True when all KafkaSource consumers has been scheduled + KafkaConditionScheduled apis.ConditionType = "Scheduled" +) + +var ( + KafkaMTSourceCondSet = apis.NewLivingConditionSet(KafkaConditionSinkProvided, KafkaConditionScheduled, KafkaConditionInitialOffsetsCommitted, KafkaConditionConnectionEstablished) +) + +func (s *KafkaSourceStatus) MarkScheduled() { + KafkaSourceCondSet.Manage(s).MarkTrue(KafkaConditionScheduled) +} + +func (s *KafkaSourceStatus) MarkNotScheduled(reason, messageFormat string, messageA ...interface{}) { + KafkaSourceCondSet.Manage(s).MarkFalse(KafkaConditionScheduled, reason, messageFormat, messageA...) +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_scheduling.go b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_scheduling.go new file mode 100644 index 0000000000..8dfdf606d0 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_scheduling.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 v1beta1 + +import ( + "k8s.io/apimachinery/pkg/types" + "knative.dev/eventing/pkg/apis/duck/v1alpha1" +) + +func (k *KafkaSource) GetKey() types.NamespacedName { + return types.NamespacedName{ + Namespace: k.Namespace, + Name: k.Name, + } +} + +func (k *KafkaSource) GetVReplicas() int32 { + if k.Spec.Consumers == nil { + return 1 + } + if k.Status.MaxAllowedVReplicas != nil { + if *k.Spec.Consumers > *k.Status.MaxAllowedVReplicas { + return *k.Status.MaxAllowedVReplicas + } + } + return *k.Spec.Consumers +} + +func (k *KafkaSource) GetPlacements() []v1alpha1.Placement { + if k.Status.Placeable.Placements == nil { + return nil + } + return k.Status.Placeable.Placements +} + +func (k *KafkaSource) GetResourceVersion() string { + return k.ObjectMeta.ResourceVersion +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_types.go b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_types.go new file mode 100644 index 0000000000..7c50e50b60 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_types.go @@ -0,0 +1,154 @@ +/* +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 v1beta1 + +import ( + "fmt" + + "knative.dev/eventing/pkg/apis/duck/v1alpha1" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + bindingsv1beta1 "knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1" + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" + "knative.dev/pkg/kmeta" + "knative.dev/pkg/webhook/resourcesemantics" +) + +// +genclient +// +genclient:method=GetScale,verb=get,subresource=scale,result=k8s.io/api/autoscaling/v1.Scale +// +genreconciler +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// KafkaSource is the Schema for the kafkasources API. +// +k8s:openapi-gen=true +type KafkaSource struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec KafkaSourceSpec `json:"spec,omitempty"` + Status KafkaSourceStatus `json:"status,omitempty"` +} + +// Check that KafkaSource can be validated and can be defaulted. +var _ runtime.Object = (*KafkaSource)(nil) +var _ resourcesemantics.GenericCRD = (*KafkaSource)(nil) +var _ kmeta.OwnerRefable = (*KafkaSource)(nil) +var _ apis.Defaultable = (*KafkaSource)(nil) +var _ apis.Validatable = (*KafkaSource)(nil) +var _ duckv1.KRShaped = (*KafkaSource)(nil) + +// KafkaSourceSpec defines the desired state of the KafkaSource. +type KafkaSourceSpec struct { + // Number of desired consumers running in the consumer group. Defaults to 1. + // + // This is a pointer to distinguish between explicit + // zero and not specified. + // +optional + Consumers *int32 `json:"consumers,omitempty"` + + bindingsv1beta1.KafkaAuthSpec `json:",inline"` + + // Topic topics to consume messages from + // +required + Topics []string `json:"topics"` + + // ConsumerGroupID is the consumer group ID. + // +optional + ConsumerGroup string `json:"consumerGroup,omitempty"` + + // InitialOffset is the Initial Offset for the consumer group. + // should be earliest or latest + // +optional + InitialOffset Offset `json:"initialOffset,omitempty"` + + // inherits duck/v1 SourceSpec, which currently provides: + // * Sink - a reference to an object that will resolve to a domain name or + // a URI directly to use as the sink. + // * CloudEventOverrides - defines overrides to control the output format + // and modifications of the event sent to the sink. + duckv1.SourceSpec `json:",inline"` +} + +type Offset string + +const ( + // KafkaEventType is the Kafka CloudEvent type. + KafkaEventType = "dev.knative.kafka.event" + + KafkaKeyTypeLabel = "kafkasources.sources.knative.dev/key-type" + + // OffsetEarliest denotes the earliest offset in the kafka partition + OffsetEarliest Offset = "earliest" + + // OffsetLatest denotes the latest offset in the kafka partition + OffsetLatest Offset = "latest" +) + +var KafkaKeyTypeAllowed = []string{"string", "int", "float", "byte-array"} + +// KafkaEventSource returns the Kafka CloudEvent source. +func KafkaEventSource(namespace, kafkaSourceName, topic string) string { + return fmt.Sprintf("/apis/v1/namespaces/%s/kafkasources/%s#%s", namespace, kafkaSourceName, topic) +} + +// KafkaSourceStatus defines the observed state of KafkaSource. +type KafkaSourceStatus struct { + // inherits duck/v1 SourceStatus, 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. + // * SinkURI - the current active sink URI that has been configured for the + // Source. + duckv1.SourceStatus `json:",inline"` + + // Total number of consumers actually running in the consumer group. + // +optional + Consumers int32 `json:"consumers,omitempty"` + + // Use for labelSelectorPath when scaling Kafka source + // +optional + Selector string `json:"selector,omitempty"` + + // Claims consumed by this KafkaSource instance + // +optional + Claims string `json:"claims,omitempty"` + + // Implement Placeable. + // +optional + v1alpha1.Placeable `json:",inline"` +} + +func (*KafkaSource) GetGroupVersionKind() schema.GroupVersionKind { + return SchemeGroupVersion.WithKind("KafkaSource") +} + +// GetStatus retrieves the duck status for this resource. Implements the KRShaped interface. +func (k *KafkaSource) GetStatus() *duckv1.Status { + return &k.Status.Status +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// KafkaSourceList contains a list of KafkaSources. +type KafkaSourceList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []KafkaSource `json:"items"` +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_validation.go b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_validation.go new file mode 100644 index 0000000000..553c85f739 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/kafka_validation.go @@ -0,0 +1,81 @@ +/* +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 v1beta1 + +import ( + "context" + + "knative.dev/pkg/apis" + "knative.dev/pkg/kmp" +) + +// Validate ensures KafkaSource is properly configured. +func (ks *KafkaSource) Validate(ctx context.Context) *apis.FieldError { + errs := ks.Spec.Validate(ctx).ViaField("spec") + if apis.IsInUpdate(ctx) { + original := apis.GetBaseline(ctx).(*KafkaSource) + errs = errs.Also(ks.CheckImmutableFields(ctx, original)) + } + return errs +} + +func (kss *KafkaSourceSpec) Validate(ctx context.Context) *apis.FieldError { + var errs *apis.FieldError + + // Validate source spec + errs = errs.Also(kss.SourceSpec.Validate(ctx)) + + // Check for mandatory fields + if len(kss.Topics) <= 0 { + errs = errs.Also(apis.ErrMissingField("topics")) + } + if len(kss.BootstrapServers) <= 0 { + errs = errs.Also(apis.ErrMissingField("bootstrapServers")) + } + switch kss.InitialOffset { + case OffsetEarliest, OffsetLatest: + default: + errs = errs.Also(apis.ErrInvalidValue(kss.InitialOffset, "initialOffset")) + } + + return errs +} + +func (ks *KafkaSource) CheckImmutableFields(ctx context.Context, original *KafkaSource) *apis.FieldError { + if original == nil { + return nil + } + diff, err := kmp.ShortDiff(original.Spec.ConsumerGroup, ks.Spec.ConsumerGroup) + + if err != nil { + return &apis.FieldError{ + Message: "Failed to diff KafkaSource", + Paths: []string{"spec"}, + Details: err.Error(), + } + } + + if diff != "" { + return &apis.FieldError{ + Message: "Immutable fields changed (-old +new)", + Paths: []string{"spec"}, + Details: diff, + } + } + + return nil +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/register.go b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/register.go new file mode 100644 index 0000000000..86996f9375 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/register.go @@ -0,0 +1,59 @@ +/* +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. +*/ + +// NOTE: Boilerplate only. Ignore this file. + +// Package v1beta1 contains API Schema definitions for the sources v1beta1 API group +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register +// +k8s:defaulter-gen=TypeMeta +// +groupName=sources.knative.dev +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "knative.dev/eventing/pkg/apis/sources" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: sources.GroupName, Version: "v1beta1"} + +// 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, + &KafkaSource{}, + &KafkaSourceList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/zz_generated.deepcopy.go b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..72294c4095 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/apis/sources/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,133 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2021 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 v1beta1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KafkaSource) DeepCopyInto(out *KafkaSource) { + *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 KafkaSource. +func (in *KafkaSource) DeepCopy() *KafkaSource { + if in == nil { + return nil + } + out := new(KafkaSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KafkaSource) 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 *KafkaSourceList) DeepCopyInto(out *KafkaSourceList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]KafkaSource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaSourceList. +func (in *KafkaSourceList) DeepCopy() *KafkaSourceList { + if in == nil { + return nil + } + out := new(KafkaSourceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KafkaSourceList) 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 *KafkaSourceSpec) DeepCopyInto(out *KafkaSourceSpec) { + *out = *in + if in.Consumers != nil { + in, out := &in.Consumers, &out.Consumers + *out = new(int32) + **out = **in + } + in.KafkaAuthSpec.DeepCopyInto(&out.KafkaAuthSpec) + if in.Topics != nil { + in, out := &in.Topics, &out.Topics + *out = make([]string, len(*in)) + copy(*out, *in) + } + in.SourceSpec.DeepCopyInto(&out.SourceSpec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaSourceSpec. +func (in *KafkaSourceSpec) DeepCopy() *KafkaSourceSpec { + if in == nil { + return nil + } + out := new(KafkaSourceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KafkaSourceStatus) DeepCopyInto(out *KafkaSourceStatus) { + *out = *in + in.SourceStatus.DeepCopyInto(&out.SourceStatus) + in.Placeable.DeepCopyInto(&out.Placeable) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaSourceStatus. +func (in *KafkaSourceStatus) DeepCopy() *KafkaSourceStatus { + if in == nil { + return nil + } + out := new(KafkaSourceStatus) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/scheme/doc.go b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/scheme/doc.go new file mode 100644 index 0000000000..5597166bea --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/scheme/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2021 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 contains the scheme of the automatically generated clientset. +package scheme diff --git a/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/scheme/register.go b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/scheme/register.go new file mode 100644 index 0000000000..04178ca46e --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/scheme/register.go @@ -0,0 +1,58 @@ +/* +Copyright 2021 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 scheme + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + bindingsv1beta1 "knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1" + sourcesv1beta1 "knative.dev/eventing-kafka/pkg/apis/sources/v1beta1" +) + +var Scheme = runtime.NewScheme() +var Codecs = serializer.NewCodecFactory(Scheme) +var ParameterCodec = runtime.NewParameterCodec(Scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + bindingsv1beta1.AddToScheme, + sourcesv1beta1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(Scheme)) +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/doc.go b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/doc.go new file mode 100644 index 0000000000..8d5037f077 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2021 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 v1beta1 diff --git a/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/fake/doc.go b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/fake/doc.go new file mode 100644 index 0000000000..d5a46ef553 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2021 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-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/fake/fake_kafkasource.go b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/fake/fake_kafkasource.go new file mode 100644 index 0000000000..f8d8be8b58 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/fake/fake_kafkasource.go @@ -0,0 +1,154 @@ +/* +Copyright 2021 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 ( + "context" + + autoscalingv1 "k8s.io/api/autoscaling/v1" + 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" + v1beta1 "knative.dev/eventing-kafka/pkg/apis/sources/v1beta1" +) + +// FakeKafkaSources implements KafkaSourceInterface +type FakeKafkaSources struct { + Fake *FakeSourcesV1beta1 + ns string +} + +var kafkasourcesResource = schema.GroupVersionResource{Group: "sources.knative.dev", Version: "v1beta1", Resource: "kafkasources"} + +var kafkasourcesKind = schema.GroupVersionKind{Group: "sources.knative.dev", Version: "v1beta1", Kind: "KafkaSource"} + +// Get takes name of the kafkaSource, and returns the corresponding kafkaSource object, and an error if there is any. +func (c *FakeKafkaSources) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.KafkaSource, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(kafkasourcesResource, c.ns, name), &v1beta1.KafkaSource{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta1.KafkaSource), err +} + +// List takes label and field selectors, and returns the list of KafkaSources that match those selectors. +func (c *FakeKafkaSources) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.KafkaSourceList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(kafkasourcesResource, kafkasourcesKind, c.ns, opts), &v1beta1.KafkaSourceList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1beta1.KafkaSourceList{ListMeta: obj.(*v1beta1.KafkaSourceList).ListMeta} + for _, item := range obj.(*v1beta1.KafkaSourceList).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 kafkaSources. +func (c *FakeKafkaSources) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(kafkasourcesResource, c.ns, opts)) + +} + +// Create takes the representation of a kafkaSource and creates it. Returns the server's representation of the kafkaSource, and an error, if there is any. +func (c *FakeKafkaSources) Create(ctx context.Context, kafkaSource *v1beta1.KafkaSource, opts v1.CreateOptions) (result *v1beta1.KafkaSource, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(kafkasourcesResource, c.ns, kafkaSource), &v1beta1.KafkaSource{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta1.KafkaSource), err +} + +// Update takes the representation of a kafkaSource and updates it. Returns the server's representation of the kafkaSource, and an error, if there is any. +func (c *FakeKafkaSources) Update(ctx context.Context, kafkaSource *v1beta1.KafkaSource, opts v1.UpdateOptions) (result *v1beta1.KafkaSource, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(kafkasourcesResource, c.ns, kafkaSource), &v1beta1.KafkaSource{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta1.KafkaSource), 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 *FakeKafkaSources) UpdateStatus(ctx context.Context, kafkaSource *v1beta1.KafkaSource, opts v1.UpdateOptions) (*v1beta1.KafkaSource, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(kafkasourcesResource, "status", c.ns, kafkaSource), &v1beta1.KafkaSource{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta1.KafkaSource), err +} + +// Delete takes name of the kafkaSource and deletes it. Returns an error if one occurs. +func (c *FakeKafkaSources) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(kafkasourcesResource, c.ns, name, opts), &v1beta1.KafkaSource{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeKafkaSources) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(kafkasourcesResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1beta1.KafkaSourceList{}) + return err +} + +// Patch applies the patch and returns the patched kafkaSource. +func (c *FakeKafkaSources) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.KafkaSource, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(kafkasourcesResource, c.ns, name, pt, data, subresources...), &v1beta1.KafkaSource{}) + + if obj == nil { + return nil, err + } + return obj.(*v1beta1.KafkaSource), err +} + +// GetScale takes name of the kafkaSource, and returns the corresponding scale object, and an error if there is any. +func (c *FakeKafkaSources) GetScale(ctx context.Context, kafkaSourceName string, options v1.GetOptions) (result *autoscalingv1.Scale, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetSubresourceAction(kafkasourcesResource, c.ns, "scale", kafkaSourceName), &autoscalingv1.Scale{}) + + if obj == nil { + return nil, err + } + return obj.(*autoscalingv1.Scale), err +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/fake/fake_sources_client.go b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/fake/fake_sources_client.go new file mode 100644 index 0000000000..e3876454b1 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/fake/fake_sources_client.go @@ -0,0 +1,40 @@ +/* +Copyright 2021 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" + v1beta1 "knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1" +) + +type FakeSourcesV1beta1 struct { + *testing.Fake +} + +func (c *FakeSourcesV1beta1) KafkaSources(namespace string) v1beta1.KafkaSourceInterface { + return &FakeKafkaSources{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeSourcesV1beta1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/generated_expansion.go b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/generated_expansion.go new file mode 100644 index 0000000000..0d52c6ea7d --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/generated_expansion.go @@ -0,0 +1,21 @@ +/* +Copyright 2021 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 v1beta1 + +type KafkaSourceExpansion interface{} diff --git a/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/kafkasource.go b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/kafkasource.go new file mode 100644 index 0000000000..d6d3305850 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/kafkasource.go @@ -0,0 +1,212 @@ +/* +Copyright 2021 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 v1beta1 + +import ( + "context" + "time" + + autoscalingv1 "k8s.io/api/autoscaling/v1" + v1 "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" + v1beta1 "knative.dev/eventing-kafka/pkg/apis/sources/v1beta1" + scheme "knative.dev/eventing-kafka/pkg/client/clientset/versioned/scheme" +) + +// KafkaSourcesGetter has a method to return a KafkaSourceInterface. +// A group's client should implement this interface. +type KafkaSourcesGetter interface { + KafkaSources(namespace string) KafkaSourceInterface +} + +// KafkaSourceInterface has methods to work with KafkaSource resources. +type KafkaSourceInterface interface { + Create(ctx context.Context, kafkaSource *v1beta1.KafkaSource, opts v1.CreateOptions) (*v1beta1.KafkaSource, error) + Update(ctx context.Context, kafkaSource *v1beta1.KafkaSource, opts v1.UpdateOptions) (*v1beta1.KafkaSource, error) + UpdateStatus(ctx context.Context, kafkaSource *v1beta1.KafkaSource, opts v1.UpdateOptions) (*v1beta1.KafkaSource, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1beta1.KafkaSource, error) + List(ctx context.Context, opts v1.ListOptions) (*v1beta1.KafkaSourceList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.KafkaSource, err error) + GetScale(ctx context.Context, kafkaSourceName string, options v1.GetOptions) (*autoscalingv1.Scale, error) + + KafkaSourceExpansion +} + +// kafkaSources implements KafkaSourceInterface +type kafkaSources struct { + client rest.Interface + ns string +} + +// newKafkaSources returns a KafkaSources +func newKafkaSources(c *SourcesV1beta1Client, namespace string) *kafkaSources { + return &kafkaSources{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the kafkaSource, and returns the corresponding kafkaSource object, and an error if there is any. +func (c *kafkaSources) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.KafkaSource, err error) { + result = &v1beta1.KafkaSource{} + err = c.client.Get(). + Namespace(c.ns). + Resource("kafkasources"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of KafkaSources that match those selectors. +func (c *kafkaSources) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.KafkaSourceList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1beta1.KafkaSourceList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("kafkasources"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested kafkaSources. +func (c *kafkaSources) Watch(ctx context.Context, opts v1.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("kafkasources"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a kafkaSource and creates it. Returns the server's representation of the kafkaSource, and an error, if there is any. +func (c *kafkaSources) Create(ctx context.Context, kafkaSource *v1beta1.KafkaSource, opts v1.CreateOptions) (result *v1beta1.KafkaSource, err error) { + result = &v1beta1.KafkaSource{} + err = c.client.Post(). + Namespace(c.ns). + Resource("kafkasources"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(kafkaSource). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a kafkaSource and updates it. Returns the server's representation of the kafkaSource, and an error, if there is any. +func (c *kafkaSources) Update(ctx context.Context, kafkaSource *v1beta1.KafkaSource, opts v1.UpdateOptions) (result *v1beta1.KafkaSource, err error) { + result = &v1beta1.KafkaSource{} + err = c.client.Put(). + Namespace(c.ns). + Resource("kafkasources"). + Name(kafkaSource.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(kafkaSource). + Do(ctx). + 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 *kafkaSources) UpdateStatus(ctx context.Context, kafkaSource *v1beta1.KafkaSource, opts v1.UpdateOptions) (result *v1beta1.KafkaSource, err error) { + result = &v1beta1.KafkaSource{} + err = c.client.Put(). + Namespace(c.ns). + Resource("kafkasources"). + Name(kafkaSource.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(kafkaSource). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the kafkaSource and deletes it. Returns an error if one occurs. +func (c *kafkaSources) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("kafkasources"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *kafkaSources) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("kafkasources"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched kafkaSource. +func (c *kafkaSources) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.KafkaSource, err error) { + result = &v1beta1.KafkaSource{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("kafkasources"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} + +// GetScale takes name of the kafkaSource, and returns the corresponding autoscalingv1.Scale object, and an error if there is any. +func (c *kafkaSources) GetScale(ctx context.Context, kafkaSourceName string, options v1.GetOptions) (result *autoscalingv1.Scale, err error) { + result = &autoscalingv1.Scale{} + err = c.client.Get(). + Namespace(c.ns). + Resource("kafkasources"). + Name(kafkaSourceName). + SubResource("scale"). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} diff --git a/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/sources_client.go b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/sources_client.go new file mode 100644 index 0000000000..f5203c6e78 --- /dev/null +++ b/vendor/knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/sources_client.go @@ -0,0 +1,107 @@ +/* +Copyright 2021 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 v1beta1 + +import ( + "net/http" + + rest "k8s.io/client-go/rest" + v1beta1 "knative.dev/eventing-kafka/pkg/apis/sources/v1beta1" + "knative.dev/eventing-kafka/pkg/client/clientset/versioned/scheme" +) + +type SourcesV1beta1Interface interface { + RESTClient() rest.Interface + KafkaSourcesGetter +} + +// SourcesV1beta1Client is used to interact with features provided by the sources.knative.dev group. +type SourcesV1beta1Client struct { + restClient rest.Interface +} + +func (c *SourcesV1beta1Client) KafkaSources(namespace string) KafkaSourceInterface { + return newKafkaSources(c, namespace) +} + +// NewForConfig creates a new SourcesV1beta1Client for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*SourcesV1beta1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + httpClient, err := rest.HTTPClientFor(&config) + if err != nil { + return nil, err + } + return NewForConfigAndClient(&config, httpClient) +} + +// NewForConfigAndClient creates a new SourcesV1beta1Client for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*SourcesV1beta1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientForConfigAndClient(&config, h) + if err != nil { + return nil, err + } + return &SourcesV1beta1Client{client}, nil +} + +// NewForConfigOrDie creates a new SourcesV1beta1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *SourcesV1beta1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new SourcesV1beta1Client for the given RESTClient. +func New(c rest.Interface) *SourcesV1beta1Client { + return &SourcesV1beta1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1beta1.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 *SourcesV1beta1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/doc.go b/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/doc.go new file mode 100644 index 0000000000..deae465ed3 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/doc.go @@ -0,0 +1,19 @@ +/* +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. +*/ + +// +k8s:deepcopy-gen=package +// +groupName=duck.knative.dev +package v1alpha1 diff --git a/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/placement_types.go b/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/placement_types.go new file mode 100644 index 0000000000..10a8686d97 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/placement_types.go @@ -0,0 +1,86 @@ +/* +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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "knative.dev/pkg/apis/duck" +) + +// +genduck + +// PlaceableType is a skeleton type wrapping Placeable in the manner we expect +// resource writers defining compatible resources to embed it. We will +// typically use this type to deserialize Placeable ObjectReferences and +// access the Placeable data. This is not a real resource. +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type PlaceableType struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Status PlaceableStatus `json:"status"` +} + +type PlaceableStatus struct { + Placeable `json:",inline"` +} + +// Placeable is a list of podName and virtual replicas pairs. +// Each pair represents the assignment of virtual replicas to a pod +type Placeable struct { + MaxAllowedVReplicas *int32 `json:"maxAllowedVReplicas,omitempty"` + Placements []Placement `json:"placements,omitempty"` +} + +type Placement struct { + // PodName is the name of the pod where the resource is placed + PodName string `json:"podName,omitempty"` + + // VReplicas is the number of virtual replicas assigned to in the pod + VReplicas int32 `json:"vreplicas,omitempty"` +} + +var ( + // Placeable is an Implementable "duck type". + _ duck.Implementable = (*Placeable)(nil) +) + +// GetFullType implements duck.Implementable +func (*Placeable) GetFullType() duck.Populatable { + return &PlaceableType{} +} + +// Populate implements duck.Populatable +func (t *PlaceableType) Populate() { + t.Status.Placements = []Placement{{PodName: "pod-0", VReplicas: int32(1)}} +} + +// GetListType implements apis.Listable +func (*PlaceableType) GetListType() runtime.Object { + return &PlaceableList{} +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// PlaceableList is a list of PlaceableType resources +type PlaceableList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []Placeable `json:"items"` +} diff --git a/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/register.go b/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/register.go new file mode 100644 index 0000000000..5057316282 --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/register.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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "knative.dev/pkg/apis/duck" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: duck.GroupName, Version: "v1alpha1"} + +// 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, + &PlaceableType{}, + (&PlaceableType{}).GetListType(), + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/zz_generated.deepcopy.go b/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..63e54bff0a --- /dev/null +++ b/vendor/knative.dev/eventing/pkg/apis/duck/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,145 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2021 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 v1alpha1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Placeable) DeepCopyInto(out *Placeable) { + *out = *in + if in.MaxAllowedVReplicas != nil { + in, out := &in.MaxAllowedVReplicas, &out.MaxAllowedVReplicas + *out = new(int32) + **out = **in + } + if in.Placements != nil { + in, out := &in.Placements, &out.Placements + *out = make([]Placement, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Placeable. +func (in *Placeable) DeepCopy() *Placeable { + if in == nil { + return nil + } + out := new(Placeable) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PlaceableList) DeepCopyInto(out *PlaceableList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Placeable, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlaceableList. +func (in *PlaceableList) DeepCopy() *PlaceableList { + if in == nil { + return nil + } + out := new(PlaceableList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PlaceableList) 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 *PlaceableStatus) DeepCopyInto(out *PlaceableStatus) { + *out = *in + in.Placeable.DeepCopyInto(&out.Placeable) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlaceableStatus. +func (in *PlaceableStatus) DeepCopy() *PlaceableStatus { + if in == nil { + return nil + } + out := new(PlaceableStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PlaceableType) DeepCopyInto(out *PlaceableType) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlaceableType. +func (in *PlaceableType) DeepCopy() *PlaceableType { + if in == nil { + return nil + } + out := new(PlaceableType) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PlaceableType) 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 *Placement) DeepCopyInto(out *Placement) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Placement. +func (in *Placement) DeepCopy() *Placement { + if in == nil { + return nil + } + out := new(Placement) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/knative.dev/kn-plugin-source-kafka/LICENSE b/vendor/knative.dev/kn-plugin-source-kafka/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/vendor/knative.dev/kn-plugin-source-kafka/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. diff --git a/vendor/knative.dev/kn-plugin-source-kafka/pkg/client/client.go b/vendor/knative.dev/kn-plugin-source-kafka/pkg/client/client.go new file mode 100644 index 0000000000..634d053cf9 --- /dev/null +++ b/vendor/knative.dev/kn-plugin-source-kafka/pkg/client/client.go @@ -0,0 +1,192 @@ +// Copyright © 2019 The Knative Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package client + +import ( + "context" + + knerrors "knative.dev/client-pkg/pkg/errors" + sourceclient "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/client" + sourcetypes "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" + v1beta1 "knative.dev/eventing-kafka/pkg/apis/sources/v1beta1" + clientv1beta1 "knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1" + "knative.dev/kn-plugin-source-kafka/pkg/types" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/rest" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +type kafkaSourceClient struct { + namespace string + kafkaSourceParams *types.KafkaSourceParams + knSourceClient sourcetypes.KnSourceClient + client clientv1beta1.SourcesV1beta1Interface +} + +// NewKafkaSourceClient is to create a KafkaSourceClient +func NewKafkaSourceClient(kafkaParams *types.KafkaSourceParams, restConfig *rest.Config, ns string) (types.KafkaSourceClient, error) { + kafkaClient, err := kafkaParams.NewSourcesClient() + if err != nil { + return nil, knerrors.GetError(err) + } + return &kafkaSourceClient{ + kafkaSourceParams: kafkaParams, + namespace: ns, + knSourceClient: sourceclient.NewKnSourceClient(kafkaParams.KnSourceParams, restConfig, ns), + client: kafkaClient, + }, nil +} + +// RestConfig the REST cconfig +func (c *kafkaSourceClient) RestConfig() *rest.Config { + return c.knSourceClient.RestConfig() +} + +// KnSourceParams for common Kn source parameters +func (c *kafkaSourceClient) KnSourceParams() *sourcetypes.KnSourceParams { + return c.kafkaSourceParams.KnSourceParams +} + +// KafkaSourceParams for kafka source specific parameters +func (c *kafkaSourceClient) KafkaSourceParams() *types.KafkaSourceParams { + return c.kafkaSourceParams +} + +// CreateKafkaSource is used to create an instance of KafkaSource +func (c *kafkaSourceClient) CreateKafkaSource(ctx context.Context, kafkaSource *v1beta1.KafkaSource) error { + _, err := c.client.KafkaSources(c.namespace).Create(ctx, kafkaSource, metav1.CreateOptions{}) + if err != nil { + return knerrors.GetError(err) + } + + return nil +} + +// DeleteKafkaSource is used to create an instance of KafkaSource +func (c *kafkaSourceClient) DeleteKafkaSource(ctx context.Context, name string) error { + err := c.client.KafkaSources(c.namespace).Delete(ctx, name, metav1.DeleteOptions{}) + if err != nil { + return knerrors.GetError(err) + } + + return nil +} + +// GetKafkaSource is used to create an instance of KafkaSource +func (c *kafkaSourceClient) GetKafkaSource(ctx context.Context, name string) (*v1beta1.KafkaSource, error) { + kafkaSource, err := c.client.KafkaSources(c.namespace).Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + + return kafkaSource, nil +} + +// ListKafkaSources is used to get all available instance of KafkaSource +func (c *kafkaSourceClient) ListKafkaSources(ctx context.Context) (*v1beta1.KafkaSourceList, error) { + kafkaSourceList, err := c.client.KafkaSources(c.namespace).List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, knerrors.GetError(err) + } + + return kafkaSourceList, nil +} + +// Return the client's namespace +func (c *kafkaSourceClient) Namespace() string { + return c.namespace +} + +// KafkaSourceBuilder is for building the source +type KafkaSourceBuilder struct { + kafkaSource *v1beta1.KafkaSource +} + +// NewKafkaSourceBuilder for building ApiServer source object +func NewKafkaSourceBuilder(name string) *KafkaSourceBuilder { + return &KafkaSourceBuilder{kafkaSource: &v1beta1.KafkaSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + }} +} + +// NewKafkaSourceBuilderFromExisting for building the object from existing KafkaSource object +func NewKafkaSourceBuilderFromExisting(kSource *v1beta1.KafkaSource) *KafkaSourceBuilder { + return &KafkaSourceBuilder{kafkaSource: kSource.DeepCopy()} +} + +// BootstrapServers to set the value of BootstrapServers +func (b *KafkaSourceBuilder) BootstrapServers(servers []string) *KafkaSourceBuilder { + b.kafkaSource.Spec.BootstrapServers = servers + return b +} + +// Topics to set the value of Topics +func (b *KafkaSourceBuilder) Topics(topics []string) *KafkaSourceBuilder { + b.kafkaSource.Spec.Topics = topics + return b +} + +// ConsumerGroup to set the value of ConsumerGroup +func (b *KafkaSourceBuilder) ConsumerGroup(consumerGroup string) *KafkaSourceBuilder { + b.kafkaSource.Spec.ConsumerGroup = consumerGroup + return b +} + +// Sink or destination of the source +func (b *KafkaSourceBuilder) Sink(sink *duckv1.Destination) *KafkaSourceBuilder { + b.kafkaSource.Spec.Sink = *sink + return b +} + +// Labels to set metadata.labels +func (b *KafkaSourceBuilder) Labels(labels map[string]string) *KafkaSourceBuilder { + b.kafkaSource.SetLabels(labels) + return b +} + +// Annotations to set metadata.annotations +func (b *KafkaSourceBuilder) Annotations(annotations map[string]string) *KafkaSourceBuilder { + b.kafkaSource.SetAnnotations(annotations) + return b +} + +// Build the KafkaSource object +func (b *KafkaSourceBuilder) Build() *v1beta1.KafkaSource { + return b.kafkaSource +} + +// CloudEventOverrides adds given Cloud Event override extensions map to source spec +func (b *KafkaSourceBuilder) CloudEventOverrides(ceo map[string]string, toRemove []string) *KafkaSourceBuilder { + if ceo == nil && len(toRemove) == 0 { + return b + } + + ceOverrides := b.kafkaSource.Spec.CloudEventOverrides + if ceOverrides == nil { + ceOverrides = &duckv1.CloudEventOverrides{Extensions: map[string]string{}} + b.kafkaSource.Spec.CloudEventOverrides = ceOverrides + } + for k, v := range ceo { + ceOverrides.Extensions[k] = v + } + for _, r := range toRemove { + delete(ceOverrides.Extensions, r) + } + + return b +} diff --git a/vendor/knative.dev/kn-plugin-source-kafka/pkg/client/client_fake.go b/vendor/knative.dev/kn-plugin-source-kafka/pkg/client/client_fake.go new file mode 100644 index 0000000000..5e5a38492a --- /dev/null +++ b/vendor/knative.dev/kn-plugin-source-kafka/pkg/client/client_fake.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 client + +import ( + "k8s.io/client-go/rest" + + sourcetypes "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes" + "knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/fake" + "knative.dev/kn-plugin-source-kafka/pkg/types" +) + +// NewFakeKafkaSourceClient is to create a fake KafkaSourceClient to test +func NewFakeKafkaSourceClient(fakeClientTest *fake.FakeSourcesV1beta1, ns string) types.KafkaSourceClient { + kafkaParams := NewFakeKafkaSourceParams() + knFakeSourceClient := &typesfakes.FakeKnSourceClient{} + knFakeSourceClient.KnSourceParamsReturns(kafkaParams.KnSourceParams) + knFakeSourceClient.NamespaceReturns(ns) + knFakeSourceClient.RestConfigReturns(&rest.Config{}) + + return &kafkaSourceClient{ + namespace: ns, + kafkaSourceParams: kafkaParams, + client: fakeClientTest, + knSourceClient: knFakeSourceClient, + } +} + +// NewFakeKafkaSourceParams is to create a fake KafkaSourceParams to test +func NewFakeKafkaSourceParams() *types.KafkaSourceParams { + return &types.KafkaSourceParams{ + KnSourceParams: &sourcetypes.KnSourceParams{}, + } +} diff --git a/vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/boilerplate.go b/vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/boilerplate.go new file mode 100644 index 0000000000..cc489b55af --- /dev/null +++ b/vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/boilerplate.go @@ -0,0 +1,79 @@ +// Copyright © 2018 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 factories + +import ( + "k8s.io/client-go/rest" + sourcetypes "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" + "knative.dev/kn-plugin-source-kafka/pkg/types" +) + +// source_factory + +func (f *kafkaClientFactory) KafkaSourceClient() types.KafkaSourceClient { + return f.kafkaSourceClient +} + +func (f *kafkaClientFactory) KnSourceParams() *sourcetypes.KnSourceParams { + return f.CreateKnSourceParams() +} + +func (f *kafkaClientFactory) CreateKnSourceParams() *sourcetypes.KnSourceParams { + if f.kafkaSourceParams == nil { + f.initKafkaSourceParams() + } + return f.kafkaSourceParams.KnSourceParams +} + +func (f *kafkaClientFactory) CreateKnSourceClient(restConfig *rest.Config, namespace string) sourcetypes.KnSourceClient { + _, err := f.CreateKafkaSourceClient(restConfig, namespace) + if err != nil { + return nil + } + return f.KafkaSourceClient() +} + +// rune_factory + +func (f *kafkaSourceRunEFactory) KnSourceParams() *sourcetypes.KnSourceParams { + return f.KafkaSourceFactory().KnSourceParams() +} + +func (f *kafkaSourceRunEFactory) KnSourceClient(restConfig *rest.Config, namespace string) sourcetypes.KnSourceClient { + return f.KafkaSourceFactory().CreateKnSourceClient(restConfig, namespace) +} + +func (f *kafkaSourceRunEFactory) KnSourceFactory() sourcetypes.KnSourceFactory { + return f.kafkaSourceFactory +} + +// flags_factory + +func (f *kafkaSourceFlagsFactory) KnSourceFactory() sourcetypes.KnSourceFactory { + return f.kafkaSourceFactory +} + +func (f *kafkaSourceFlagsFactory) KnSourceParams() *sourcetypes.KnSourceParams { + return f.kafkaSourceFactory.KnSourceParams() +} + +// command_factory +func (f *kafkaSourceCommandFactory) KnSourceFactory() sourcetypes.KnSourceFactory { + return f.kafkaSourceFactory +} + +func (f *kafkaSourceCommandFactory) KnSourceParams() *sourcetypes.KnSourceParams { + return f.kafkaSourceFactory.KnSourceParams() +} diff --git a/vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/command_factory.go b/vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/command_factory.go new file mode 100644 index 0000000000..0118ad964d --- /dev/null +++ b/vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/command_factory.go @@ -0,0 +1,96 @@ +// Copyright © 2018 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 factories + +import ( + "knative.dev/kn-plugin-source-kafka/pkg/types" + + sourcefactories "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories" + sourcetypes "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" + + "github.com/spf13/cobra" +) + +type kafkaSourceCommandFactory struct { + kafkaSourceFactory types.KafkaSourceFactory + defaultCommandFactory sourcetypes.CommandFactory +} + +func NewKafkaSourceCommandFactory(kafkaFactory types.KafkaSourceFactory) types.KafkaSourceCommandFactory { + return &kafkaSourceCommandFactory{ + kafkaSourceFactory: kafkaFactory, + defaultCommandFactory: sourcefactories.NewDefaultCommandFactory(kafkaFactory), + } +} + +func (f *kafkaSourceCommandFactory) KafkaSourceFactory() types.KafkaSourceFactory { + return f.kafkaSourceFactory +} + +func (f *kafkaSourceCommandFactory) KafkaSourceParams() *types.KafkaSourceParams { + return f.kafkaSourceFactory.KafkaSourceParams() +} + +func (f *kafkaSourceCommandFactory) SourceCommand() *cobra.Command { + sourceCmd := f.defaultCommandFactory.SourceCommand() + sourceCmd.Use = "kafka" + sourceCmd.Short = "Knative eventing kafka source plugin" + sourceCmd.Long = "Manage Knative kafka eventing sources" + return sourceCmd +} + +func (f *kafkaSourceCommandFactory) CreateCommand() *cobra.Command { + createCmd := f.defaultCommandFactory.CreateCommand() + createCmd.Use = "create NAME --servers SERVERS --topics TOPICS --sink SINK" + createCmd.Short = "Create a kafka source" + createCmd.Example = `# Create a new kafka source 'mykafkasrc' which subscribes a kafka server 'my-cluster-kafka-bootstrap.kafka.svc:9092' at topic 'test-topic' and sends the events to service 'event-display' +kn source kafka create mykafkasrc --servers my-cluster-kafka-bootstrap.kafka.svc:9092 --topics test-topic --sink svc:event-display + +# Create a new kafka source 'mykafkasrc' which subscribes a kafka server 'my-cluster-kafka-bootstrap.kafka.svc:9092' at topic 'test-topic' using the consumer group ID 'test-consumer-group' and sends the events to service 'event-display' +kn source kafka create mykafkasrc --servers my-cluster-kafka-bootstrap.kafka.svc:9092 --topics test-topic --consumergroup test-consumer-group --sink svc:event-display --ce-override "sink=bound" +` + return createCmd +} + +func (f *kafkaSourceCommandFactory) DeleteCommand() *cobra.Command { + deleteCmd := f.defaultCommandFactory.DeleteCommand() + deleteCmd.Use = "delete NAME" + deleteCmd.Short = "Delete a kafka source" + deleteCmd.Example = `# Delete a kafka source with name 'mykafkasrc' +kn source kafka delete mykafkasrc` + return deleteCmd +} + +func (f *kafkaSourceCommandFactory) UpdateCommand() *cobra.Command { + return nil +} + +func (f *kafkaSourceCommandFactory) DescribeCommand() *cobra.Command { + describeCmd := f.defaultCommandFactory.DescribeCommand() + describeCmd.Use = "describe NAME" + describeCmd.Short = "Describe a kafka source" + describeCmd.Example = `# Describe a kafka source with NAME +kn source kafka describe kafka-name` + return describeCmd +} + +func (f *kafkaSourceCommandFactory) ListCommand() *cobra.Command { + listCmd := f.defaultCommandFactory.ListCommand() + listCmd.Use = "list" + listCmd.Short = "List kafka sources" + listCmd.Example = `# List the available kafka sources +kn source kafka list` + return listCmd +} diff --git a/vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/flags_factory.go b/vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/flags_factory.go new file mode 100644 index 0000000000..1fd414ddb5 --- /dev/null +++ b/vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/flags_factory.go @@ -0,0 +1,79 @@ +// Copyright © 2018 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 factories + +import ( + sourcefactories "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories" + sourcetypes "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" + + "knative.dev/kn-plugin-source-kafka/pkg/types" + + "github.com/spf13/pflag" +) + +type kafkaSourceFlagsFactory struct { + defaultFlagsFactory sourcetypes.FlagsFactory + kafkaSourceFactory types.KafkaSourceFactory +} + +func NewKafkaSourceFlagsFactory(kafkaFactory types.KafkaSourceFactory) types.KafkaSourceFlagsFactory { + return &kafkaSourceFlagsFactory{ + defaultFlagsFactory: sourcefactories.NewDefaultFlagsFactory(kafkaFactory), + kafkaSourceFactory: kafkaFactory, + } +} + +func (f *kafkaSourceFlagsFactory) KafkaSourceParams() *types.KafkaSourceParams { + return f.kafkaSourceFactory.KafkaSourceParams() +} + +func (f *kafkaSourceFlagsFactory) KafkaSourceFactory() types.KafkaSourceFactory { + return f.kafkaSourceFactory +} + +func (f *kafkaSourceFlagsFactory) CreateFlags() *pflag.FlagSet { + flagSet := pflag.NewFlagSet("create", pflag.ExitOnError) + flagSet.StringArrayVar(&f.KafkaSourceParams().BootstrapServers, "servers", []string{}, "Kafka bootstrap servers that the consumer will connect to, consist of a hostname plus a port pair, e.g. my-kafka-bootstrap.kafka:9092. Flag can be used multiple times.") + flagSet.StringArrayVar(&f.KafkaSourceParams().Topics, "topics", []string{}, "Topics to consume messages from. Flag can be used multiple times.") + flagSet.StringVar(&f.KafkaSourceParams().ConsumerGroup, "consumergroup", "", "the consumer group ID") + flagSet.StringArrayVar(&f.KafkaSourceParams().CeOverrides, "ce-override", []string{}, "Cloud Event overrides to apply before sending event to sink. "+ + "Example: '--ce-override key=value' "+ + "You may be provide this flag multiple times. "+ + "To unset, append \"-\" to the key (e.g. --ce-override key-).") + flagSet.StringArrayVarP(&f.KafkaSourceParams().Labels, "label", "l", []string{}, "Metadata labels to set on the resources. "+ + "Example: '--label key=value' "+ + "You may be provide this flag multiple times.") + flagSet.StringArrayVarP(&f.KafkaSourceParams().Annotations, "annotation", "a", []string{}, "Metadata annotations to set on the resources. "+ + "Example: '--annotation key=value' "+ + "You may be provide this flag multiple times.") + return flagSet +} + +func (f *kafkaSourceFlagsFactory) DeleteFlags() *pflag.FlagSet { + return pflag.NewFlagSet("delete", pflag.ExitOnError) +} + +func (f *kafkaSourceFlagsFactory) UpdateFlags() *pflag.FlagSet { + flagSet := pflag.NewFlagSet("update", pflag.ExitOnError) + return flagSet +} + +func (f *kafkaSourceFlagsFactory) DescribeFlags() *pflag.FlagSet { + return pflag.NewFlagSet("describe", pflag.ExitOnError) +} + +func (f *kafkaSourceFlagsFactory) ListFlags() *pflag.FlagSet { + return pflag.NewFlagSet("list", pflag.ExitOnError) +} diff --git a/vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/rune_factory.go b/vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/rune_factory.go new file mode 100644 index 0000000000..46cc7adce1 --- /dev/null +++ b/vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/rune_factory.go @@ -0,0 +1,371 @@ +// Copyright © 2018 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 factories + +import ( + "errors" + "fmt" + "sort" + "strings" + + v1beta1 "knative.dev/eventing-kafka/pkg/apis/sources/v1beta1" + "knative.dev/kn-plugin-source-kafka/pkg/client" + "knative.dev/kn-plugin-source-kafka/pkg/types" + + sourcetypes "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" + + "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/rest" + "knative.dev/client-pkg/pkg/kn/commands" + "knative.dev/client-pkg/pkg/kn/commands/flags" + "knative.dev/client-pkg/pkg/printers" + "knative.dev/client-pkg/pkg/util" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +// Max column size +const listColumnMaxLength = 50 + +type kafkaSourceRunEFactory struct { + kafkaSourceClient types.KafkaSourceClient + kafkaSourceFactory types.KafkaSourceFactory +} + +func NewKafkaSourceRunEFactory(kafkaFactory types.KafkaSourceFactory) types.KafkaSourceRunEFactory { + return &kafkaSourceRunEFactory{ + kafkaSourceFactory: kafkaFactory, + kafkaSourceClient: kafkaFactory.KafkaSourceClient(), + } +} + +func NewFakeKafkaSourceRunEFactory(ns string) types.KafkaSourceRunEFactory { + kafkaFactory := NewFakeKafkaSourceFactory(ns) + return &kafkaSourceRunEFactory{ + kafkaSourceFactory: kafkaFactory, + kafkaSourceClient: kafkaFactory.KafkaSourceClient(), + } +} + +func (f *kafkaSourceRunEFactory) KafkaSourceClient(restConfig *rest.Config, namespace string) (types.KafkaSourceClient, error) { + var err error + f.kafkaSourceClient, err = f.KafkaSourceFactory().CreateKafkaSourceClient(restConfig, namespace) + return f.kafkaSourceClient, err +} + +func (f *kafkaSourceRunEFactory) KafkaSourceFactory() types.KafkaSourceFactory { + return f.kafkaSourceFactory +} + +func (f *kafkaSourceRunEFactory) CreateRunE() sourcetypes.RunE { + return func(cmd *cobra.Command, args []string) error { + var err error + namespace, err := f.KnSourceParams().GetNamespace(cmd) + if err != nil { + return err + } + + restConfig, err := f.KnSourceParams().KnParams.RestConfig() + if err != nil { + return err + } + + f.kafkaSourceClient, err = f.KafkaSourceClient(restConfig, namespace) + if err != nil { + return err + } + + if len(args) != 1 { + return errors.New("requires the name of the source to create as single argument") + } + name := args[0] + + dynamicClient, err := f.KnSourceParams().KnParams.NewDynamicClient(f.kafkaSourceClient.Namespace()) + if err != nil { + return err + } + objectRef, err := f.KnSourceParams().SinkFlag.ResolveSink(cmd.Context(), dynamicClient, f.kafkaSourceClient.Namespace()) + if err != nil { + return fmt.Errorf( + "cannot create kafka '%s' in namespace '%s' "+ + "because: %s", name, f.kafkaSourceClient.Namespace(), err) + } + obj, err := createKafkaSource(name, f.kafkaSourceFactory.KafkaSourceParams(), objectRef) + if err != nil { + return err + } + err = f.kafkaSourceClient.CreateKafkaSource(cmd.Context(), obj) + + if err != nil { + return fmt.Errorf( + "cannot create KafkaSource '%s' in namespace '%s' "+ + "because: %s", name, f.kafkaSourceClient.Namespace(), err) + } + + fmt.Fprintf(cmd.OutOrStdout(), "Kafka source '%s' created in namespace '%s'.\n", name, f.kafkaSourceClient.Namespace()) + return nil + } +} + +func createKafkaSource(name string, params *types.KafkaSourceParams, sink *duckv1.Destination) (*v1beta1.KafkaSource, error) { + ceOverridesMap, err := util.MapFromArrayAllowingSingles(params.CeOverrides, "=") + if err != nil { + return nil, err + } + ceOverridesToRemove := util.ParseMinusSuffix(ceOverridesMap) + b := client.NewKafkaSourceBuilder(name). + BootstrapServers(params.BootstrapServers). + Topics(params.Topics). + ConsumerGroup(params.ConsumerGroup). + Sink(sink). + CloudEventOverrides(ceOverridesMap, ceOverridesToRemove) + return b.Build(), nil +} + +func (f *kafkaSourceRunEFactory) DeleteRunE() sourcetypes.RunE { + return func(cmd *cobra.Command, args []string) error { + var err error + namespace, err := f.KnSourceParams().GetNamespace(cmd) + if err != nil { + return err + } + + restConfig, err := f.KnSourceParams().KnParams.RestConfig() + if err != nil { + return err + } + + f.kafkaSourceClient, err = f.KafkaSourceClient(restConfig, namespace) + if err != nil { + return err + } + + if len(args) != 1 { + return errors.New("requires the name of the source to create as single argument") + } + name := args[0] + + err = f.kafkaSourceClient.DeleteKafkaSource(cmd.Context(), name) + + if err != nil { + return fmt.Errorf( + "cannot delete KafkaSource '%s' in namespace '%s' "+ + "because: %s", name, f.kafkaSourceClient.Namespace(), err) + } + + fmt.Fprintf(cmd.OutOrStdout(), "Kafka source '%s' deleted in namespace '%s'.\n", name, f.kafkaSourceClient.Namespace()) + return nil + } +} + +func (f *kafkaSourceRunEFactory) UpdateRunE() sourcetypes.RunE { + return func(cmd *cobra.Command, args []string) error { + fmt.Printf("Kafka source update is not supported because kafka source spec is immutable.\n") + return nil + } +} + +func (f *kafkaSourceRunEFactory) DescribeRunE() sourcetypes.RunE { + return func(cmd *cobra.Command, args []string) error { + var err error + namespace, err := f.KnSourceParams().GetNamespace(cmd) + if err != nil { + return err + } + + restConfig, err := f.KnSourceParams().KnParams.RestConfig() + if err != nil { + return err + } + + f.kafkaSourceClient, err = f.KafkaSourceClient(restConfig, namespace) + if err != nil { + return err + } + + if len(args) != 1 { + return errors.New("requires the name of the source to create as single argument") + } + name := args[0] + + kafkaSource, err := f.kafkaSourceClient.GetKafkaSource(cmd.Context(), name) + + if err != nil { + return fmt.Errorf( + "cannot describe KafkaSource '%s' in namespace '%s' "+ + "because: %s", name, f.kafkaSourceClient.Namespace(), err) + } + + out := cmd.OutOrStdout() + dw := printers.NewPrefixWriter(out) + + writeKafkaSource(dw, kafkaSource) + dw.WriteLine() + if err := dw.Flush(); err != nil { + return err + } + + if kafkaSource.Spec.Sink.Ref != nil { + writeSink(dw, kafkaSource.Spec.Sink) + dw.WriteLine() + if err := dw.Flush(); err != nil { + return err + } + } + + if kafkaSource.Spec.CloudEventOverrides != nil { + writeCeOverrides(dw, kafkaSource.Spec.CloudEventOverrides.Extensions) + if err := dw.Flush(); err != nil { + return err + } + } + + commands.WriteConditions(dw, kafkaSource.Status.Conditions, true) + if err := dw.Flush(); err != nil { + return err + } + return nil + } +} + +func (f *kafkaSourceRunEFactory) ListRunE() sourcetypes.RunE { + return func(cmd *cobra.Command, args []string) error { + var err error + namespace, err := f.KnSourceParams().GetNamespace(cmd) + if err != nil { + return err + } + restConfig, err := f.KnSourceParams().KnParams.RestConfig() + if err != nil { + return err + } + + f.kafkaSourceClient, err = f.KafkaSourceClient(restConfig, namespace) + if err != nil { + return err + } + + kafkaSourceList, err := f.kafkaSourceClient.ListKafkaSources(cmd.Context()) + + if err != nil { + return fmt.Errorf( + "cannot list KafkaSources in namespace '%s' "+ + "because: %s", f.kafkaSourceClient.Namespace(), err) + } + if len(kafkaSourceList.Items) == 0 { + return fmt.Errorf("no kafka source found in namespace '%s'", f.kafkaSourceClient.Namespace()) + } + + printer := printers.NewTableGenerator() + kafkaSourceListColumnDefinitions := []metav1.TableColumnDefinition{ + {Name: "Name", Type: "string", Description: "Name of the created kafka source", Priority: 1}, + {Name: "Age", Type: "string", Description: "Age of the kafka source", Priority: 1}, + {Name: "Sink", Type: "string", Description: "Sink of the kafka source", Priority: 1}, + {Name: "BootstrapServers", Type: "string", Description: "Kafka bootstrap server", Priority: 1}, + } + err = printer.TableHandler(kafkaSourceListColumnDefinitions, printKafkaSource) + if err != nil { + return err + } + err = printer.TableHandler(kafkaSourceListColumnDefinitions, printKafkaSourceList) + if err != nil { + return err + } + err = printer.PrintObj(kafkaSourceList, cmd.OutOrStdout()) + if err != nil { + return err + } + return nil + } +} + +func writeSink(dw printers.PrefixWriter, sink duckv1.Destination) { + subWriter := dw.WriteAttribute("Sink", "") + ref := sink.Ref + if ref != nil { + subWriter.WriteAttribute("Name", sink.Ref.Name) + if sink.Ref.Namespace != "" { + subWriter.WriteAttribute("Namespace", sink.Ref.Namespace) + } + subWriter.WriteAttribute("Resource", fmt.Sprintf("%s (%s)", sink.Ref.Kind, sink.Ref.APIVersion)) + } + uri := sink.URI + if uri != nil { + subWriter.WriteAttribute("URI", uri.String()) + } +} + +func writeCeOverrides(dw printers.PrefixWriter, ceOverrides map[string]string) { + subDw := dw.WriteAttribute("CloudEvent Overrides", "") + keys := make([]string, 0, len(ceOverrides)) + for k := range ceOverrides { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + subDw.WriteAttribute(k, ceOverrides[k]) + } +} + +func writeKafkaSource(dw printers.PrefixWriter, source *v1beta1.KafkaSource) { + commands.WriteMetadata(dw, &source.ObjectMeta, true) + dw.WriteAttribute("BootstrapServers", strings.Join(source.Spec.BootstrapServers, ", ")) + dw.WriteAttribute("Topics", strings.Join(source.Spec.Topics, ",")) + dw.WriteAttribute("ConsumerGroup", source.Spec.ConsumerGroup) +} + +// printKafkaSource populates a single row of kafka source list table +func printKafkaSource(kafkaSource *v1beta1.KafkaSource, options printers.PrintOptions) ([]metav1.TableRow, error) { + row := metav1.TableRow{ + Object: runtime.RawExtension{Object: kafkaSource}, + } + + if options.AllNamespaces { + row.Cells = append(row.Cells, kafkaSource.ObjectMeta.Namespace) + } + + row.Cells = append(row.Cells, + trunc(kafkaSource.ObjectMeta.Name), + commands.Age(kafkaSource.ObjectMeta.CreationTimestamp.Time), + trunc(flags.SinkToString(kafkaSource.Spec.Sink)), + trunc(strings.Join(kafkaSource.Spec.BootstrapServers, ",")), + ) + return []metav1.TableRow{row}, nil +} + +// printKafkaSourceList populates the kafka source list table rows +func printKafkaSourceList(sourceList *v1beta1.KafkaSourceList, options printers.PrintOptions) ([]metav1.TableRow, error) { + rows := make([]metav1.TableRow, 0, len(sourceList.Items)) + + sort.SliceStable(sourceList.Items, func(i, j int) bool { + return sourceList.Items[i].ObjectMeta.Name < sourceList.Items[j].ObjectMeta.Name + }) + for _, source := range sourceList.Items { + row, err := printKafkaSource(&source, options) + if err != nil { + return nil, err + } + rows = append(rows, row...) + } + return rows, nil +} + +func trunc(txt string) string { + if len(txt) <= listColumnMaxLength { + return txt + } + return txt[:listColumnMaxLength-4] + " ..." +} diff --git a/vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/source_factory.go b/vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/source_factory.go new file mode 100644 index 0000000000..cecb28fd8c --- /dev/null +++ b/vendor/knative.dev/kn-plugin-source-kafka/pkg/factories/source_factory.go @@ -0,0 +1,84 @@ +// Copyright © 2018 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 factories + +import ( + "k8s.io/client-go/rest" + client_testing "k8s.io/client-go/testing" + sourcefactories "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories" + sourcetypes "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" + "knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/fake" + "knative.dev/kn-plugin-source-kafka/pkg/client" + "knative.dev/kn-plugin-source-kafka/pkg/types" +) + +type kafkaClientFactory struct { + kafkaSourceParams *types.KafkaSourceParams + kafkaSourceClient types.KafkaSourceClient + knSourceFactory sourcetypes.KnSourceFactory +} + +func NewKafkaSourceFactory() types.KafkaSourceFactory { + return &kafkaClientFactory{ + kafkaSourceParams: nil, + kafkaSourceClient: nil, + knSourceFactory: sourcefactories.NewDefaultKnSourceFactory(), + } +} + +func NewFakeKafkaSourceFactory(ns string) types.KafkaSourceFactory { + fakeClient := fake.FakeSourcesV1beta1{Fake: &client_testing.Fake{}} + fakeSourceClient := client.NewFakeKafkaSourceClient(&fakeClient, ns) + fakeParams := fakeSourceClient.KafkaSourceParams() + return &kafkaClientFactory{ + kafkaSourceParams: fakeParams, + kafkaSourceClient: fakeSourceClient, + knSourceFactory: sourcefactories.NewDefaultKnSourceFactory(), + } +} + +func (f *kafkaClientFactory) CreateKafkaSourceClient(restConfig *rest.Config, namespace string) (types.KafkaSourceClient, error) { + var err error + if f.kafkaSourceClient == nil { + f.kafkaSourceClient, err = client.NewKafkaSourceClient(f.KafkaSourceParams(), restConfig, namespace) + if err != nil { + return nil, err + } + } + return f.kafkaSourceClient, nil +} + +func (f *kafkaClientFactory) KafkaSourceParams() *types.KafkaSourceParams { + if f.kafkaSourceParams == nil { + f.initKafkaSourceParams() + } + return f.kafkaSourceParams +} + +func (f *kafkaClientFactory) CreateKafkaSourceParams() *types.KafkaSourceParams { + if f.kafkaSourceParams == nil { + f.initKafkaSourceParams() + } + return f.kafkaSourceParams +} + +// Private + +func (f *kafkaClientFactory) initKafkaSourceParams() { + f.kafkaSourceParams = &types.KafkaSourceParams{ + KnSourceParams: f.knSourceFactory.CreateKnSourceParams(), + } + f.kafkaSourceParams.KnSourceParams.Initialize() +} diff --git a/vendor/knative.dev/kn-plugin-source-kafka/pkg/root/root.go b/vendor/knative.dev/kn-plugin-source-kafka/pkg/root/root.go new file mode 100644 index 0000000000..722f15fec2 --- /dev/null +++ b/vendor/knative.dev/kn-plugin-source-kafka/pkg/root/root.go @@ -0,0 +1,33 @@ +// 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 root + +import ( + "github.com/spf13/cobra" + "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/core" + + "knative.dev/kn-plugin-source-kafka/pkg/factories" +) + +// NewSourceKafkaCommand represents the plugin's entrypoint +func NewSourceKafkaCommand() *cobra.Command { + kafkaSourceFactory := factories.NewKafkaSourceFactory() + + kafkaCommandFactory := factories.NewKafkaSourceCommandFactory(kafkaSourceFactory) + kafkaFlagsFactory := factories.NewKafkaSourceFlagsFactory(kafkaSourceFactory) + kafkaRunEFactory := factories.NewKafkaSourceRunEFactory(kafkaSourceFactory) + + return core.NewKnSourceCommand(kafkaSourceFactory, kafkaCommandFactory, kafkaFlagsFactory, kafkaRunEFactory) +} diff --git a/vendor/knative.dev/kn-plugin-source-kafka/pkg/types/interfaces.go b/vendor/knative.dev/kn-plugin-source-kafka/pkg/types/interfaces.go new file mode 100644 index 0000000000..962e750e33 --- /dev/null +++ b/vendor/knative.dev/kn-plugin-source-kafka/pkg/types/interfaces.go @@ -0,0 +1,62 @@ +// Copyright © 2018 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 types + +import ( + "context" + + v1beta1 "knative.dev/eventing-kafka/pkg/apis/sources/v1beta1" + + "k8s.io/client-go/rest" + sourcetypes "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" +) + +type KafkaSourceClient interface { + sourcetypes.KnSourceClient + KafkaSourceParams() *KafkaSourceParams + CreateKafkaSource(ctx context.Context, kafkaSource *v1beta1.KafkaSource) error + DeleteKafkaSource(ctx context.Context, name string) error + GetKafkaSource(ctx context.Context, name string) (*v1beta1.KafkaSource, error) + ListKafkaSources(ctx context.Context) (*v1beta1.KafkaSourceList, error) +} + +type KafkaSourceFactory interface { + sourcetypes.KnSourceFactory + + KafkaSourceParams() *KafkaSourceParams + KafkaSourceClient() KafkaSourceClient + + CreateKafkaSourceClient(restConfig *rest.Config, namespace string) (KafkaSourceClient, error) + CreateKafkaSourceParams() *KafkaSourceParams +} + +type KafkaSourceCommandFactory interface { + sourcetypes.CommandFactory + + KafkaSourceFactory() KafkaSourceFactory +} + +type KafkaSourceFlagsFactory interface { + sourcetypes.FlagsFactory + + KafkaSourceFactory() KafkaSourceFactory +} + +type KafkaSourceRunEFactory interface { + sourcetypes.RunEFactory + + KafkaSourceFactory() KafkaSourceFactory + KafkaSourceClient(restConfig *rest.Config, namespace string) (KafkaSourceClient, error) +} diff --git a/vendor/knative.dev/kn-plugin-source-kafka/pkg/types/structs.go b/vendor/knative.dev/kn-plugin-source-kafka/pkg/types/structs.go new file mode 100644 index 0000000000..c25a82cc48 --- /dev/null +++ b/vendor/knative.dev/kn-plugin-source-kafka/pkg/types/structs.go @@ -0,0 +1,40 @@ +// Copyright © 2018 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 types + +import ( + sourcetypes "knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types" + clientv1beta1 "knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1" +) + +type KafkaSourceParams struct { + KnSourceParams *sourcetypes.KnSourceParams + BootstrapServers []string + Topics []string + ConsumerGroup string + CeOverrides []string + Labels []string + Annotations []string +} + +func (p *KafkaSourceParams) NewSourcesClient() (*clientv1beta1.SourcesV1beta1Client, error) { + restConfig, err := p.KnSourceParams.RestConfig() + if err != nil { + return nil, err + } + + c, _ := clientv1beta1.NewForConfig(restConfig) + return c, nil +} diff --git a/vendor/knative.dev/kn-plugin-source-kafka/plugin/plugin.go b/vendor/knative.dev/kn-plugin-source-kafka/plugin/plugin.go new file mode 100644 index 0000000000..0a291658f2 --- /dev/null +++ b/vendor/knative.dev/kn-plugin-source-kafka/plugin/plugin.go @@ -0,0 +1,60 @@ +// 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 plugin + +import ( + "os" + + "knative.dev/kn-plugin-source-kafka/pkg/root" + + "knative.dev/client-pkg/pkg/kn/plugin" +) + +func init() { + plugin.InternalPlugins = append(plugin.InternalPlugins, &sourceKafkaPlugin{}) +} + +type sourceKafkaPlugin struct{} + +// Name is a plugin's name +func (l *sourceKafkaPlugin) Name() string { + return "kn-source-kafka" +} + +// Execute represents the plugin's entrypoint when called through kn +func (l *sourceKafkaPlugin) Execute(args []string) error { + cmd := root.NewSourceKafkaCommand() + oldArgs := os.Args + defer (func() { + os.Args = oldArgs + })() + os.Args = append([]string{"kn-source-kafka"}, args...) + return cmd.Execute() +} + +// Description is displayed in kn's plugin section +func (l *sourceKafkaPlugin) Description() (string, error) { + return "Manage Kafka sources", nil +} + +// CommandParts defines for plugin is executed from kn +func (l *sourceKafkaPlugin) CommandParts() []string { + return []string{"source", "kafka"} +} + +// Path is empty because its an internal plugins +func (l *sourceKafkaPlugin) Path() string { + return "" +} diff --git a/vendor/knative.dev/pkg/apis/duck/v1alpha1/addressable_types.go b/vendor/knative.dev/pkg/apis/duck/v1alpha1/addressable_types.go new file mode 100644 index 0000000000..e0399f55d5 --- /dev/null +++ b/vendor/knative.dev/pkg/apis/duck/v1alpha1/addressable_types.go @@ -0,0 +1,174 @@ +/* +Copyright 2018 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 v1alpha1 + +import ( + "context" + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + "knative.dev/pkg/apis" + "knative.dev/pkg/apis/duck" + v1 "knative.dev/pkg/apis/duck/v1" + "knative.dev/pkg/apis/duck/v1beta1" +) + +// +genduck + +// Addressable provides a generic mechanism for a custom resource +// definition to indicate a destination for message delivery. +// +// Addressable is the schema for the destination information. This is +// typically stored in the object's `status`, as this information may +// be generated by the controller. +type Addressable struct { + v1beta1.Addressable `json:",omitempty"` + + Hostname string `json:"hostname,omitempty"` +} + +var ( + // Addressable is an Implementable "duck type". + _ duck.Implementable = (*Addressable)(nil) + // Addressable is a Convertible type. + _ apis.Convertible = (*Addressable)(nil) +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// AddressableType is a skeleton type wrapping Addressable in the manner we expect +// resource writers defining compatible resources to embed it. We will +// typically use this type to deserialize Addressable ObjectReferences and +// access the Addressable data. This is not a real resource. +type AddressableType struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Status AddressStatus `json:"status"` +} + +// AddressStatus shows how we expect folks to embed Addressable in +// their Status field. +type AddressStatus struct { + // Address is a single Addressable address. + // If Addresses is present, Address will be ignored by clients. + // +optional + Address *Addressable `json:"address,omitempty"` + + // Addresses is a list of addresses for different protocols (HTTP and HTTPS) + // If Addresses is present, Address must be ignored by clients. + // +optional + Addresses []Addressable `json:"addresses,omitempty"` +} + +var ( + // Verify AddressableType resources meet duck contracts. + _ duck.Populatable = (*AddressableType)(nil) + _ apis.Listable = (*AddressableType)(nil) +) + +// GetFullType implements duck.Implementable +func (*Addressable) GetFullType() duck.Populatable { + return &AddressableType{} +} + +// ConvertTo implements apis.Convertible +func (a *Addressable) ConvertTo(ctx context.Context, to apis.Convertible) error { + var url *apis.URL + if a.URL != nil { + url = a.URL + } else if a.Hostname != "" { + u := a.GetURL() + url = &u + } + switch sink := to.(type) { + case *v1.Addressable: + sink.URL = url.DeepCopy() + return nil + case *v1beta1.Addressable: + sink.URL = url.DeepCopy() + return nil + default: + return fmt.Errorf("unknown version, got: %T", to) + } +} + +// ConvertFrom implements apis.Convertible +func (a *Addressable) ConvertFrom(ctx context.Context, from apis.Convertible) error { + switch source := from.(type) { + case *v1.Addressable: + a.URL = source.URL.DeepCopy() + if a.URL != nil { + a.Hostname = a.URL.Host + } + return nil + case *v1beta1.Addressable: + a.URL = source.URL.DeepCopy() + if a.URL != nil { + a.Hostname = a.URL.Host + } + return nil + default: + return fmt.Errorf("unknown version, got: %T", from) + } +} + +// Populate implements duck.Populatable +func (t *AddressableType) Populate() { + name := "http" + t.Status = AddressStatus{ + Address: &Addressable{ + // Populate ALL fields + Addressable: v1beta1.Addressable{ + Name: &name, + URL: &apis.URL{ + Scheme: "http", + Host: "foo.bar.svc.cluster.local", + }, + }, + Hostname: "this is not empty", + }, + } +} + +// GetURL returns the URL type for the Addressable. +func (a Addressable) GetURL() apis.URL { + if a.URL != nil { + return *a.URL + } + return apis.URL{ + Scheme: "http", + Host: a.Hostname, + } +} + +// GetListType implements apis.Listable +func (*AddressableType) GetListType() runtime.Object { + return &AddressableTypeList{} +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// AddressableTypeList is a list of AddressableType resources +type AddressableTypeList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []AddressableType `json:"items"` +} diff --git a/vendor/knative.dev/pkg/apis/duck/v1alpha1/binding_types.go b/vendor/knative.dev/pkg/apis/duck/v1alpha1/binding_types.go new file mode 100644 index 0000000000..168439686c --- /dev/null +++ b/vendor/knative.dev/pkg/apis/duck/v1alpha1/binding_types.go @@ -0,0 +1,92 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + "knative.dev/pkg/apis" + "knative.dev/pkg/apis/duck" + "knative.dev/pkg/tracker" +) + +// +genduck +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Binding is a duck type that specifies the partial schema to which all +// Binding implementations should adhere. +type Binding struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec BindingSpec `json:"spec"` +} + +// Verify that Binding implements the appropriate interfaces. +var ( + _ duck.Implementable = (*Binding)(nil) + _ duck.Populatable = (*Binding)(nil) + _ apis.Listable = (*Binding)(nil) +) + +// BindingSpec specifies the spec portion of the Binding partial-schema. +type BindingSpec struct { + // Subject references the resource(s) whose "runtime contract" should be + // augmented by Binding implementations. + Subject tracker.Reference `json:"subject"` +} + +// GetFullType implements duck.Implementable +func (*Binding) GetFullType() duck.Populatable { + return &Binding{} +} + +// Populate implements duck.Populatable +func (t *Binding) Populate() { + t.Spec = BindingSpec{ + Subject: tracker.Reference{ + APIVersion: "apps/v1", + Kind: "Deployment", + Namespace: "default", + // Name and Selector are mutually exclusive, + // but we fill them both in for this test. + Name: "bazinga", + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "foo": "bar", + "baz": "blah", + }, + }, + }, + } +} + +// GetListType implements apis.Listable +func (*Binding) GetListType() runtime.Object { + return &BindingList{} +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// BindingList is a list of Binding resources +type BindingList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []Binding `json:"items"` +} diff --git a/vendor/knative.dev/pkg/apis/duck/v1alpha1/doc.go b/vendor/knative.dev/pkg/apis/duck/v1alpha1/doc.go new file mode 100644 index 0000000000..3638eb7a30 --- /dev/null +++ b/vendor/knative.dev/pkg/apis/duck/v1alpha1/doc.go @@ -0,0 +1,23 @@ +/* +Copyright 2018 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 + +// +k8s:deepcopy-gen=package +// +groupName=duck.knative.dev +package v1alpha1 diff --git a/vendor/knative.dev/pkg/apis/duck/v1alpha1/legacy_targetable_types.go b/vendor/knative.dev/pkg/apis/duck/v1alpha1/legacy_targetable_types.go new file mode 100644 index 0000000000..09513ff03e --- /dev/null +++ b/vendor/knative.dev/pkg/apis/duck/v1alpha1/legacy_targetable_types.go @@ -0,0 +1,96 @@ +/* +Copyright 2018 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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + "knative.dev/pkg/apis" + "knative.dev/pkg/apis/duck" +) + +// +genduck + +// LegacyTargetable left around until we migrate to Addressable in the +// dependent resources. Addressable has more structure in the way it +// defines the fields. LegacyTargetable only assumed a single string +// in the Status field and we're moving towards defining proper structs +// under Status rather than strings. +// This is to support existing resources until they migrate. +// +// # Do not use this for anything new, use Addressable +// +// LegacyTargetable is the old schema for the addressable portion +// of the payload +// +// For new resources use Addressable. +type LegacyTargetable struct { + DomainInternal string `json:"domainInternal,omitempty"` +} + +// LegacyTargetable is an Implementable "duck type". +var _ duck.Implementable = (*LegacyTargetable)(nil) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// LegacyTarget is a skeleton type wrapping LegacyTargetable in the manner we +// want to support unless they get migrated into supporting Legacy. +// We will typically use this type to deserialize LegacyTargetable +// ObjectReferences and access the LegacyTargetable data. This is not a +// real resource. +// ** Do not use this for any new resources ** +type LegacyTarget struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Status LegacyTargetable `json:"status"` +} + +// In order for LegacyTargetable to be Implementable, LegacyTarget must be Populatable. +var _ duck.Populatable = (*LegacyTarget)(nil) + +// Ensure LegacyTarget satisfies apis.Listable +var _ apis.Listable = (*LegacyTarget)(nil) + +// GetFullType implements duck.Implementable +func (*LegacyTargetable) GetFullType() duck.Populatable { + return &LegacyTarget{} +} + +// Populate implements duck.Populatable +func (t *LegacyTarget) Populate() { + t.Status = LegacyTargetable{ + // Populate ALL fields + DomainInternal: "this is not empty", + } +} + +// GetListType implements apis.Listable +func (*LegacyTarget) GetListType() runtime.Object { + return &LegacyTargetList{} +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// LegacyTargetList is a list of LegacyTarget resources +type LegacyTargetList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []LegacyTarget `json:"items"` +} diff --git a/vendor/knative.dev/pkg/apis/duck/v1alpha1/register.go b/vendor/knative.dev/pkg/apis/duck/v1alpha1/register.go new file mode 100644 index 0000000000..333bae39dd --- /dev/null +++ b/vendor/knative.dev/pkg/apis/duck/v1alpha1/register.go @@ -0,0 +1,59 @@ +/* +Copyright 2018 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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "knative.dev/pkg/apis/duck" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: duck.GroupName, Version: "v1alpha1"} + +// 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 builds a scheme with the types known to the package. + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // AddToScheme adds the types known to this package to an existing schema. + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes( + SchemeGroupVersion, + &AddressableType{}, + (&AddressableType{}).GetListType(), + &Target{}, + (&Target{}).GetListType(), + &LegacyTarget{}, + (&LegacyTarget{}).GetListType(), + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/knative.dev/pkg/apis/duck/v1alpha1/retired_targetable_types.go b/vendor/knative.dev/pkg/apis/duck/v1alpha1/retired_targetable_types.go new file mode 100644 index 0000000000..d8afb324a4 --- /dev/null +++ b/vendor/knative.dev/pkg/apis/duck/v1alpha1/retired_targetable_types.go @@ -0,0 +1,100 @@ +/* +Copyright 2018 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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + "knative.dev/pkg/apis" + "knative.dev/pkg/apis/duck" +) + +// +genduck + +// Targetable is an earlier version of the Callable interface. +// Callable is a higher-level interface which implements Addressable +// but further promises that the destination may synchronously return +// response messages in reply to a message. +// +// Targetable implementations should instead implement Addressable and +// include an `eventing.knative.dev/returns=any` annotation. +// +// Targetable is retired; implement Addressable for now. +type Targetable struct { + DomainInternal string `json:"domainInternal,omitempty"` +} + +// Targetable is an Implementable "duck type". +var _ duck.Implementable = (*Targetable)(nil) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Target is a skeleton type wrapping Targetable in the manner we expect +// resource writers defining compatible resources to embed it. We will +// typically use this type to deserialize Targetable ObjectReferences and +// access the Targetable data. This is not a real resource. +type Target struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Status TargetStatus `json:"status"` +} + +// TargetStatus shows how we expect folks to embed Targetable in +// their Status field. +type TargetStatus struct { + Targetable *Targetable `json:"targetable,omitempty"` +} + +var ( + // In order for Targetable to be Implementable, Target must be Populatable. + _ duck.Populatable = (*Target)(nil) + + // Ensure Target satisfies apis.Listable + _ apis.Listable = (*Target)(nil) +) + +// GetFullType implements duck.Implementable +func (*Targetable) GetFullType() duck.Populatable { + return &Target{} +} + +// Populate implements duck.Populatable +func (t *Target) Populate() { + t.Status = TargetStatus{ + &Targetable{ + // Populate ALL fields + DomainInternal: "this is not empty", + }, + } +} + +// GetListType implements apis.Listable +func (*Target) GetListType() runtime.Object { + return &TargetList{} +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// TargetList is a list of Target resources +type TargetList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []Target `json:"items"` +} diff --git a/vendor/knative.dev/pkg/apis/duck/v1alpha1/zz_generated.deepcopy.go b/vendor/knative.dev/pkg/apis/duck/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..4c9d622365 --- /dev/null +++ b/vendor/knative.dev/pkg/apis/duck/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,381 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2022 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 v1alpha1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddressStatus) DeepCopyInto(out *AddressStatus) { + *out = *in + if in.Address != nil { + in, out := &in.Address, &out.Address + *out = new(Addressable) + (*in).DeepCopyInto(*out) + } + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]Addressable, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressStatus. +func (in *AddressStatus) DeepCopy() *AddressStatus { + if in == nil { + return nil + } + out := new(AddressStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Addressable) DeepCopyInto(out *Addressable) { + *out = *in + in.Addressable.DeepCopyInto(&out.Addressable) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Addressable. +func (in *Addressable) DeepCopy() *Addressable { + if in == nil { + return nil + } + out := new(Addressable) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddressableType) DeepCopyInto(out *AddressableType) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressableType. +func (in *AddressableType) DeepCopy() *AddressableType { + if in == nil { + return nil + } + out := new(AddressableType) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AddressableType) 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 *AddressableTypeList) DeepCopyInto(out *AddressableTypeList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]AddressableType, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressableTypeList. +func (in *AddressableTypeList) DeepCopy() *AddressableTypeList { + if in == nil { + return nil + } + out := new(AddressableTypeList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AddressableTypeList) 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 *Binding) DeepCopyInto(out *Binding) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Binding. +func (in *Binding) DeepCopy() *Binding { + if in == nil { + return nil + } + out := new(Binding) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Binding) 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 *BindingList) DeepCopyInto(out *BindingList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Binding, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BindingList. +func (in *BindingList) DeepCopy() *BindingList { + if in == nil { + return nil + } + out := new(BindingList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BindingList) 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 *BindingSpec) DeepCopyInto(out *BindingSpec) { + *out = *in + in.Subject.DeepCopyInto(&out.Subject) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BindingSpec. +func (in *BindingSpec) DeepCopy() *BindingSpec { + if in == nil { + return nil + } + out := new(BindingSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LegacyTarget) DeepCopyInto(out *LegacyTarget) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Status = in.Status + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LegacyTarget. +func (in *LegacyTarget) DeepCopy() *LegacyTarget { + if in == nil { + return nil + } + out := new(LegacyTarget) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LegacyTarget) 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 *LegacyTargetList) DeepCopyInto(out *LegacyTargetList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]LegacyTarget, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LegacyTargetList. +func (in *LegacyTargetList) DeepCopy() *LegacyTargetList { + if in == nil { + return nil + } + out := new(LegacyTargetList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LegacyTargetList) 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 *LegacyTargetable) DeepCopyInto(out *LegacyTargetable) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LegacyTargetable. +func (in *LegacyTargetable) DeepCopy() *LegacyTargetable { + if in == nil { + return nil + } + out := new(LegacyTargetable) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Target) DeepCopyInto(out *Target) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Target. +func (in *Target) DeepCopy() *Target { + if in == nil { + return nil + } + out := new(Target) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Target) 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 *TargetList) DeepCopyInto(out *TargetList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Target, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetList. +func (in *TargetList) DeepCopy() *TargetList { + if in == nil { + return nil + } + out := new(TargetList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TargetList) 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 *TargetStatus) DeepCopyInto(out *TargetStatus) { + *out = *in + if in.Targetable != nil { + in, out := &in.Targetable, &out.Targetable + *out = new(Targetable) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetStatus. +func (in *TargetStatus) DeepCopy() *TargetStatus { + if in == nil { + return nil + } + out := new(TargetStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Targetable) DeepCopyInto(out *Targetable) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Targetable. +func (in *Targetable) DeepCopy() *Targetable { + if in == nil { + return nil + } + out := new(Targetable) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/knative.dev/pkg/apis/testing/fuzzer/fuzzer.go b/vendor/knative.dev/pkg/apis/testing/fuzzer/fuzzer.go new file mode 100644 index 0000000000..412ff195a6 --- /dev/null +++ b/vendor/knative.dev/pkg/apis/testing/fuzzer/fuzzer.go @@ -0,0 +1,103 @@ +/* +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 fuzzer + +import ( + "math/rand" + "net/url" + + fuzz "github.com/google/gofuzz" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/apitesting/fuzzer" + "k8s.io/apimachinery/pkg/runtime/serializer" + "knative.dev/pkg/apis" +) + +// Funcs includes fuzzing funcs for knative.dev/serving types +// +// For other examples see +// https://github.com/kubernetes/apimachinery/blob/master/pkg/apis/meta/fuzzer/fuzzer.go +var Funcs = fuzzer.MergeFuzzerFuncs( + func(codecs serializer.CodecFactory) []interface{} { + return []interface{}{ + func(u *apis.URL, c fuzz.Continue) { + u.Scheme = randStringAtoZ(c.Rand) + u.Host = randStringAtoZ(c.Rand) + u.User = url.UserPassword( + randStringAtoZ(c.Rand), // username + randStringAtoZ(c.Rand), // password + ) + u.RawPath = url.PathEscape(c.RandString()) + u.RawQuery = url.QueryEscape(c.RandString()) + }, + } + }, +) + +// FuzzConditions fuzzes the values for the conditions. It doesn't add +// any new condition types +// +// Consumers should initialize their conditions prior to fuzzing them. +// For example: +// +// func(s *SomeStatus, c fuzz.Continue) { +// c.FuzzNoCustom(s) // fuzz the status object +// +// // Clear the random fuzzed condition +// s.Status.SetConditions(nil) +// +// // Fuzz the known conditions except their type value +// s.InitializeConditions() +// fuzz.Conditions(&s.Status, c) +// } +func FuzzConditions(accessor apis.ConditionsAccessor, c fuzz.Continue) { + conds := accessor.GetConditions() + for i, cond := range conds { + // Leave condition.Type untouched + cond.Status = corev1.ConditionStatus(c.RandString()) + cond.Severity = apis.ConditionSeverity(c.RandString()) + cond.Message = c.RandString() + cond.Reason = c.RandString() + c.FuzzNoCustom(&cond.LastTransitionTime) + conds[i] = cond + } + accessor.SetConditions(conds) +} + +// taken from gofuzz internals for RandString +type charRange struct { + first, last rune +} + +func (c *charRange) choose(r *rand.Rand) rune { + count := int64(c.last - c.first + 1) + ch := c.first + rune(r.Int63n(count)) + + return ch +} + +// not fully exhaustive +func randStringAtoZ(r *rand.Rand) string { + hostCharRange := charRange{'a', 'z'} + + n := r.Intn(20) + runes := make([]rune, n) + for i := range runes { + runes[i] = hostCharRange.choose(r) + } + return string(runes) +} diff --git a/vendor/knative.dev/pkg/webhook/resourcesemantics/interface.go b/vendor/knative.dev/pkg/webhook/resourcesemantics/interface.go new file mode 100644 index 0000000000..aa989894d5 --- /dev/null +++ b/vendor/knative.dev/pkg/webhook/resourcesemantics/interface.go @@ -0,0 +1,50 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resourcesemantics + +import ( + admissionregistrationv1 "k8s.io/api/admissionregistration/v1" + "k8s.io/apimachinery/pkg/runtime" + "knative.dev/pkg/apis" +) + +// GenericCRD is the interface definition that allows us to perform the generic +// CRD actions like deciding whether to increment generation and so forth. +type GenericCRD interface { + apis.Defaultable + apis.Validatable + runtime.Object +} + +// VerbLimited defines which Verbs you want to have the webhook invoked on. +type VerbLimited interface { + // SupportedVerbs define which operations (verbs) webhook is called on. + SupportedVerbs() []admissionregistrationv1.OperationType +} + +// SubResourceLimited defines which subresources you want to have the webhook +// invoked on. For example "status", "scale", etc. +type SubResourceLimited interface { + // SupportedSubResources are the subresources that will be registered + // for the resource validation. + // If you wanted to add for example scale validation for Deployments, you'd + // do: + // []string{"", "/status", "/scale"} + // And to get just the main resource, you would do: + // []string{""} + SupportedSubResources() []string +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 2c10c0a65e..56c69a033a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -641,6 +641,7 @@ k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1 # k8s.io/apimachinery v0.25.4 ## explicit; go 1.19 +k8s.io/apimachinery/pkg/api/apitesting/fuzzer k8s.io/apimachinery/pkg/api/equality k8s.io/apimachinery/pkg/api/errors k8s.io/apimachinery/pkg/api/meta @@ -968,11 +969,41 @@ k8s.io/utils/net k8s.io/utils/pointer k8s.io/utils/strings/slices k8s.io/utils/trace +# knative.dev/client-pkg v0.0.0-20230425201444-4f052f9ef2f2 +## explicit; go 1.18 +knative.dev/client-pkg/pkg/config +knative.dev/client-pkg/pkg/dynamic +knative.dev/client-pkg/pkg/dynamic/fake +knative.dev/client-pkg/pkg/errors +knative.dev/client-pkg/pkg/eventing/v1 +knative.dev/client-pkg/pkg/eventing/v1beta1 +knative.dev/client-pkg/pkg/kn-source-pkg/pkg/client +knative.dev/client-pkg/pkg/kn-source-pkg/pkg/commands/source +knative.dev/client-pkg/pkg/kn-source-pkg/pkg/core +knative.dev/client-pkg/pkg/kn-source-pkg/pkg/factories +knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types +knative.dev/client-pkg/pkg/kn-source-pkg/pkg/types/typesfakes +knative.dev/client-pkg/pkg/kn/commands +knative.dev/client-pkg/pkg/kn/commands/flags +knative.dev/client-pkg/pkg/kn/config +knative.dev/client-pkg/pkg/kn/flags +knative.dev/client-pkg/pkg/kn/plugin +knative.dev/client-pkg/pkg/messaging/v1 +knative.dev/client-pkg/pkg/printers +knative.dev/client-pkg/pkg/serving +knative.dev/client-pkg/pkg/serving/v1 +knative.dev/client-pkg/pkg/serving/v1alpha1 +knative.dev/client-pkg/pkg/sources/v1 +knative.dev/client-pkg/pkg/sources/v1beta2 +knative.dev/client-pkg/pkg/util +knative.dev/client-pkg/pkg/util/mock +knative.dev/client-pkg/pkg/wait # knative.dev/eventing v0.37.0 ## explicit; go 1.19 knative.dev/eventing/pkg/apis/config 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/eventing knative.dev/eventing/pkg/apis/eventing/v1 knative.dev/eventing/pkg/apis/eventing/v1beta1 @@ -996,9 +1027,25 @@ knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1 knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1/fake knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1beta2 knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1beta2/fake +# knative.dev/eventing-kafka v0.37.0 +## explicit; go 1.19 +knative.dev/eventing-kafka/pkg/apis/bindings +knative.dev/eventing-kafka/pkg/apis/bindings/v1beta1 +knative.dev/eventing-kafka/pkg/apis/sources/config +knative.dev/eventing-kafka/pkg/apis/sources/v1beta1 +knative.dev/eventing-kafka/pkg/client/clientset/versioned/scheme +knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1 +knative.dev/eventing-kafka/pkg/client/clientset/versioned/typed/sources/v1beta1/fake # knative.dev/hack v0.0.0-20230417170854-f591fea109b3 ## explicit; go 1.18 knative.dev/hack +# knative.dev/kn-plugin-source-kafka v0.37.0 +## explicit; go 1.18 +knative.dev/kn-plugin-source-kafka/pkg/client +knative.dev/kn-plugin-source-kafka/pkg/factories +knative.dev/kn-plugin-source-kafka/pkg/root +knative.dev/kn-plugin-source-kafka/pkg/types +knative.dev/kn-plugin-source-kafka/plugin # knative.dev/networking v0.0.0-20230419144338-e5d04e805e50 ## explicit; go 1.18 knative.dev/networking/pkg @@ -1020,7 +1067,9 @@ knative.dev/pkg/apis knative.dev/pkg/apis/duck knative.dev/pkg/apis/duck/ducktypes knative.dev/pkg/apis/duck/v1 +knative.dev/pkg/apis/duck/v1alpha1 knative.dev/pkg/apis/duck/v1beta1 +knative.dev/pkg/apis/testing/fuzzer knative.dev/pkg/changeset knative.dev/pkg/client/injection/ducks/duck/v1/addressable knative.dev/pkg/codegen/cmd/injection-gen @@ -1064,6 +1113,7 @@ knative.dev/pkg/tracing/config knative.dev/pkg/tracing/propagation knative.dev/pkg/tracing/propagation/tracecontextb3 knative.dev/pkg/tracker +knative.dev/pkg/webhook/resourcesemantics # knative.dev/serving v0.37.0 ## explicit; go 1.18 knative.dev/serving/pkg/apis/autoscaling