From b68b94abb38b8318bd97c6a0a86873e2accad07f Mon Sep 17 00:00:00 2001 From: Vaibhav Date: Thu, 25 Apr 2019 14:42:07 -0400 Subject: [PATCH] Resource version validation (#268) * chore(): moving gateway configmaps to event source directory * chore(): moving gateway configmaps to event source directory * updating event source definitions with better comments * updating event source definitions with better comments * updating gateway, event-source and sensor examples * updating gateway, event-source and sensor examples * started amending logger * adding tests for event sources * adding tests for event sources * adding check for event source version before processing it in watcher. adding func and file name in log. * adding comments to trun ssl on webhook and adding formatter to logger * updating event source examples * adding back gateway and sensor guide * fix e2e test * fix e2e test * fix e2e test * add ca-certs to community gateways * updating docs structure * updating docs * updating docs * updating docs * updating docs * updating docs * updating docs * update version to v0.10 * update e2e test images * fix e2e test * fix e2e test * fix e2e test * fix e2e test * fix e2e test * fix event source --- .travis.yml | 2 +- Gopkg.lock | 43 +- README.md | 101 +--- ROADMAP.md | 6 +- VERSION | 2 +- common/common.go | 85 +-- common/events.go | 2 +- common/logger.go | 137 +---- common/retry.go | 8 + common/util.go | 11 + controllers/gateway/config.go | 6 +- controllers/gateway/controller.go | 31 +- controllers/gateway/informer.go | 15 +- controllers/gateway/operator.go | 35 +- controllers/gateway/operator_test.go | 3 +- controllers/gateway/resource.go | 2 +- controllers/gateway/state.go | 5 +- controllers/gateway/validate.go | 8 +- controllers/gateway/validate_test.go | 4 - controllers/sensor/config.go | 6 +- controllers/sensor/controller.go | 31 +- controllers/sensor/informer.go | 13 +- controllers/sensor/informer_test.go | 2 +- controllers/sensor/operator.go | 33 +- controllers/sensor/state.go | 9 +- controllers/sensor/validate.go | 90 ++- docs/_config.yml | 1 - docs/assets/calendar.png | Bin 1334 -> 0 bytes docs/assets/file.png | Bin 1706 -> 0 bytes docs/assets/github-logo.png | Bin 1754 -> 0 bytes docs/assets/gitlab.png | Bin 1916 -> 0 bytes docs/assets/k8s.png | Bin 12690 -> 0 bytes docs/assets/netapp.png | Bin 695 -> 0 bytes docs/assets/pubsub.png | Bin 29683 -> 0 bytes docs/assets/s3.png | Bin 7335 -> 0 bytes docs/assets/slack.png | Bin 3829 -> 0 bytes docs/assets/sns.png | Bin 4634 -> 0 bytes docs/assets/sqs.png | Bin 11978 -> 0 bytes docs/assets/stream.png | Bin 1482 -> 0 bytes docs/assets/webhook.png | Bin 3446 -> 0 bytes docs/gateway-guide.md | 31 +- docs/gateway-protocol.md | 223 -------- .../README.md => docs/gateways/artifact.md | 13 +- .../README.md => docs/gateways/aws-sns.md | 14 +- .../README.md => docs/gateways/aws-sqs.md | 12 +- .../README.md => docs/gateways/calendar.md | 12 +- .../file/README.md => docs/gateways/file.md | 12 +- .../README.md => docs/gateways/gcp-pubsub.md | 12 +- .../README.md => docs/gateways/github.md | 14 +- .../README.md => docs/gateways/gitlab.md | 15 +- .../README.md => docs/gateways/resource.md | 13 +- .../slack/README.md => docs/gateways/slack.md | 12 +- .../gateways/storage-grid.md | 12 +- .../README.md => docs/gateways/streams.md | 18 +- .../README.md => docs/gateways/webhook.md | 18 +- docs/index.md | 101 ++++ docs/sensor-guide.md | 1 - docs/sensor-protocol.md | 541 ------------------ docs/setup.md | 15 - docs/trigger-guide.md | 2 +- examples/event-sources/amqp.yaml | 36 ++ examples/event-sources/artifact.yaml | 61 ++ examples/event-sources/aws-sns.yaml | 58 ++ examples/event-sources/aws-sqs.yaml | 42 ++ examples/event-sources/calendar.yaml | 44 ++ examples/event-sources/file.yaml | 25 + examples/event-sources/gcp-pubsub.yaml | 19 + examples/event-sources/github.yaml | 77 +++ examples/event-sources/gitlab.yaml | 55 ++ .../hdfs.yaml} | 8 +- examples/event-sources/kafka.yaml | 33 ++ examples/event-sources/mqtt.yaml | 34 ++ examples/event-sources/nats.yaml | 32 ++ examples/event-sources/resource.yaml | 84 +++ examples/event-sources/slack.yaml | 46 ++ examples/event-sources/storage-grid.yaml | 38 ++ examples/event-sources/webhook.yaml | 41 ++ examples/gateways/amqp-gateway-configmap.yaml | 15 - examples/gateways/amqp.yaml | 18 +- .../gateways/artifact-gateway-configmap.yaml | 22 - examples/gateways/artifact-nats-standard.yaml | 10 +- .../gateways/artifact-nats-streaming.yaml | 10 +- .../{artifact-http.yaml => artifact.yaml} | 8 +- .../gateways/aws-sns-gateway-configmap.yaml | 19 - examples/gateways/aws-sns.yaml | 10 +- .../gateways/aws-sqs-gateway-configmap.yaml | 15 - examples/gateways/aws-sqs.yaml | 10 +- .../gateways/calendar-gateway-configmap.yaml | 9 - examples/gateways/calendar.yaml | 10 +- examples/gateways/file-gateway-configmap.yaml | 9 - examples/gateways/file.yaml | 10 +- .../gcp-pubsub-gateway-configmap.yaml | 9 - examples/gateways/gcp-pubsub.yaml | 10 +- .../gateways/github-gateway-configmap.yaml | 24 - examples/gateways/github.yaml | 10 +- .../gateways/gitlab-gateway-configmap.yaml | 18 - examples/gateways/gitlab.yaml | 10 +- examples/gateways/hdfs.yaml | 10 +- .../gateways/kafka-gateway-configmap.yaml | 13 - examples/gateways/kafka.yaml | 10 +- examples/gateways/mqtt-gateway-configmap.yaml | 11 - examples/gateways/mqtt.yaml | 10 +- examples/gateways/multi-watchers.yaml | 10 +- examples/gateways/nats-gateway-configmap.yaml | 8 - examples/gateways/nats.yaml | 10 +- .../gateways/resource-gateway-configmap.yaml | 21 - examples/gateways/resource.yaml | 10 +- .../secure-webhook-gateway-configmap.yaml | 13 - examples/gateways/secure-webhook.yaml | 8 +- .../gateways/slack-gateway-configmap.yaml | 13 - examples/gateways/slack.yaml | 10 +- .../storage-grid-gateway-configmap.yaml | 11 - examples/gateways/storage-grid.yaml | 10 +- .../gateways/trello-gateway-configmap.yaml | 17 - examples/gateways/trello.yaml | 45 -- .../gateways/webhook-gateway-configmap.yaml | 13 - examples/gateways/webhook-nats-standard.yaml | 10 +- examples/gateways/webhook-nats-streaming.yaml | 10 +- .../{webhook-http.yaml => webhook.yaml} | 25 +- examples/sensors/amqp.yaml | 8 +- .../artifact-with-param-nats-standard.yaml | 8 +- .../artifact-with-param-nats-streaming.yaml | 8 +- examples/sensors/artifact.yaml | 10 +- examples/sensors/aws-sns.yaml | 8 +- examples/sensors/aws-sqs.yaml | 8 +- examples/sensors/calendar.yaml | 8 +- .../complete-trigger-parameterization.yaml | 18 +- examples/sensors/context-filter-webhook.yaml | 6 +- examples/sensors/data-filter-webhook.yaml | 11 +- ...yaml => dependencies-circuit-complex.yaml} | 6 +- ...boolean.yaml => dependencies-circuit.yaml} | 6 +- examples/sensors/file.yaml | 10 +- examples/sensors/gcp-pubsub.yaml | 8 +- examples/sensors/github.yaml | 8 +- examples/sensors/gitlab.yaml | 10 +- examples/sensors/hdfs.yaml | 10 +- examples/sensors/kafka.yaml | 8 +- examples/sensors/mqtt-sensor.yaml | 8 +- examples/sensors/multi-signal-sensor.yaml | 26 +- examples/sensors/multi-trigger-sensor.yaml | 5 +- examples/sensors/nats.yaml | 9 +- examples/sensors/resource.yaml | 9 +- examples/sensors/slack.yaml | 7 +- examples/sensors/storage-grid.yaml | 7 +- examples/sensors/time-filter-webhook.yaml | 5 +- examples/sensors/trello.yaml | 52 -- examples/sensors/trigger-gateway.yaml | 21 +- .../sensors/trigger-source-configmap.yaml | 5 +- ...e-sensor.yaml => trigger-source-file.yaml} | 4 + examples/sensors/trigger-source-git.yaml | 3 + .../trigger-standard-k8s-resource.yaml | 3 + ...backoff.yaml => trigger-with-backoff.yaml} | 3 + examples/sensors/url-sensor.yaml | 3 + examples/sensors/webhook-nats-streaming.yaml | 7 +- examples/sensors/webhook-nats.yaml | 7 +- .../webhook-with-complete-payload.yaml | 53 -- .../sensors/webhook-with-resource-param.yaml | 53 -- .../{webhook-http.yaml => webhook.yaml} | 9 +- gateways/Dockerfile | 2 +- gateways/common/validate.go | 10 +- gateways/common/validate_test.go | 42 +- gateways/common/webhook.go | 20 +- gateways/community/aws-sns/Dockerfile | 3 +- gateways/community/aws-sns/config.go | 6 +- gateways/community/aws-sns/start.go | 29 +- gateways/community/aws-sns/validate.go | 2 +- gateways/community/aws-sns/validate_test.go | 75 +-- gateways/community/aws-sqs/Dockerfile | 3 +- gateways/community/aws-sqs/config.go | 6 +- gateways/community/aws-sqs/start.go | 10 +- gateways/community/aws-sqs/validate.go | 2 +- gateways/community/aws-sqs/validate_test.go | 75 +-- gateways/community/gcp-pubsub/Dockerfile | 7 +- gateways/community/gcp-pubsub/config.go | 6 +- gateways/community/gcp-pubsub/start.go | 13 +- gateways/community/gcp-pubsub/validate.go | 2 +- .../community/gcp-pubsub/validate_test.go | 63 +- gateways/community/github/config.go | 6 +- gateways/community/github/start.go | 18 +- gateways/community/github/tokenauth.go | 13 + gateways/community/github/validate.go | 2 +- gateways/community/github/validate_test.go | 92 ++- gateways/community/gitlab/Dockerfile | 3 +- gateways/community/gitlab/config.go | 8 +- gateways/community/gitlab/start.go | 22 +- gateways/community/gitlab/validate.go | 5 +- gateways/community/gitlab/validate_test.go | 78 +-- gateways/community/hdfs/config.go | 6 +- gateways/community/hdfs/start.go | 5 +- gateways/community/hdfs/validate.go | 2 +- gateways/community/hdfs/validate_test.go | 69 +-- gateways/community/slack/config.go | 6 +- gateways/community/slack/start.go | 14 +- gateways/community/slack/validate.go | 2 +- gateways/community/slack/validate_test.go | 66 +-- gateways/community/storagegrid/config.go | 6 +- gateways/community/storagegrid/start.go | 18 +- gateways/community/storagegrid/validate.go | 2 +- .../community/storagegrid/validate_test.go | 74 +-- gateways/config.go | 23 +- gateways/core/artifact/config.go | 6 +- gateways/core/artifact/start.go | 7 +- gateways/core/artifact/validate.go | 2 +- gateways/core/artifact/validate_test.go | 81 +-- gateways/core/calendar/config.go | 6 +- gateways/core/calendar/start.go | 8 +- gateways/core/calendar/validate.go | 2 +- gateways/core/calendar/validate_test.go | 59 +- gateways/core/file/config.go | 6 +- gateways/core/file/start.go | 7 +- gateways/core/file/validate.go | 2 +- gateways/core/file/validate_test.go | 61 +- gateways/core/resource/config.go | 6 +- gateways/core/resource/start.go | 10 +- gateways/core/resource/validate.go | 2 +- gateways/core/resource/validate_test.go | 74 +-- gateways/core/stream/amqp/config.go | 8 +- gateways/core/stream/amqp/start.go | 13 +- gateways/core/stream/amqp/validate.go | 2 +- gateways/core/stream/amqp/validate_test.go | 64 +-- gateways/core/stream/kafka/config.go | 8 +- gateways/core/stream/kafka/start.go | 18 +- gateways/core/stream/kafka/validate.go | 2 +- gateways/core/stream/kafka/validate_test.go | 61 +- gateways/core/stream/mqtt/config.go | 8 +- gateways/core/stream/mqtt/start.go | 17 +- gateways/core/stream/mqtt/validate.go | 2 +- gateways/core/stream/mqtt/validate_test.go | 65 +-- gateways/core/stream/nats/config.go | 8 +- gateways/core/stream/nats/start.go | 19 +- gateways/core/stream/nats/validate.go | 2 +- gateways/core/stream/nats/validate_test.go | 62 +- gateways/core/webhook/config.go | 6 +- gateways/core/webhook/start.go | 10 +- gateways/core/webhook/validate.go | 8 +- gateways/core/webhook/validate_test.go | 76 +-- gateways/event-source_test.go | 6 +- gateways/event-sources.go | 62 +- gateways/eventing.pb.go | 42 +- gateways/eventing.proto | 2 + gateways/gateway.go | 9 +- gateways/state.go | 5 +- gateways/transformer.go | 17 +- gateways/watcher.go | 25 +- hack/e2e/cleanup-e2e.sh | 5 - hack/e2e/kind-run-e2e.sh | 38 +- .../manifests/argo-events-cluster-roles.yaml | 94 --- hack/e2e/manifests/argo-events-sa.yaml | 5 - .../gateway-controller-configmap.yaml | 9 - .../gateway-controller-deployment.yaml | 11 +- .../sensor-controller-configmap.yaml | 9 - .../sensor-controller-deployment.yaml | 11 +- hack/e2e/run-e2e.sh | 22 - hack/e2e/setup-e2e.sh | 4 +- .../gateway-controller-deployment.yaml | 5 +- .../sensor-controller-deployment.yaml | 5 +- mkdocs.yml | 42 ++ .../gateway/v1alpha1/openapi_generated.go | 13 +- pkg/apis/gateway/v1alpha1/types.go | 18 +- pkg/apis/sensor/v1alpha1/openapi_generated.go | 4 +- pkg/apis/sensor/v1alpha1/types.go | 2 + .../sensor/v1alpha1/zz_generated.deepcopy.go | 6 +- sensors/config.go | 5 +- sensors/event-handler.go | 2 +- sensors/http-events-handler.go | 6 +- sensors/nats-events-handler.go | 14 +- sensors/signal-filter.go | 12 +- sensors/trigger.go | 2 +- test/e2e/common/client.go | 233 +------- test/e2e/common/constants.go | 6 - test/e2e/common/manifests/namespace.yaml | 7 - test/e2e/common/manifests/rolebinding.yaml | 13 - test/e2e/common/misc.go | 28 - test/e2e/core/main_test.go | 183 +++--- .../webhook-gateway-configmap.yaml | 9 - .../webhook-gateway-event-source.yaml | 15 + .../general-use-case/webhook-gateway.yaml | 31 +- .../general-use-case/webhook-sensor.yaml | 8 +- version.go | 2 +- 279 files changed, 2770 insertions(+), 3518 deletions(-) delete mode 100644 docs/_config.yml delete mode 100644 docs/assets/calendar.png delete mode 100644 docs/assets/file.png delete mode 100644 docs/assets/github-logo.png delete mode 100644 docs/assets/gitlab.png delete mode 100644 docs/assets/k8s.png delete mode 100644 docs/assets/netapp.png delete mode 100644 docs/assets/pubsub.png delete mode 100644 docs/assets/s3.png delete mode 100644 docs/assets/slack.png delete mode 100644 docs/assets/sns.png delete mode 100644 docs/assets/sqs.png delete mode 100644 docs/assets/stream.png delete mode 100644 docs/assets/webhook.png delete mode 100644 docs/gateway-protocol.md rename gateways/core/artifact/README.md => docs/gateways/artifact.md (77%) rename gateways/community/aws-sns/README.md => docs/gateways/aws-sns.md (69%) rename gateways/community/aws-sqs/README.md => docs/gateways/aws-sqs.md (58%) rename gateways/core/calendar/README.md => docs/gateways/calendar.md (82%) rename gateways/core/file/README.md => docs/gateways/file.md (76%) rename gateways/community/gcp-pubsub/README.md => docs/gateways/gcp-pubsub.md (60%) rename gateways/community/github/README.md => docs/gateways/github.md (67%) rename gateways/community/gitlab/README.md => docs/gateways/gitlab.md (63%) rename gateways/core/resource/README.md => docs/gateways/resource.md (74%) rename gateways/community/slack/README.md => docs/gateways/slack.md (70%) rename gateways/community/storagegrid/README.md => docs/gateways/storage-grid.md (81%) rename gateways/core/stream/README.md => docs/gateways/streams.md (57%) rename gateways/core/webhook/README.md => docs/gateways/webhook.md (81%) create mode 100644 docs/index.md delete mode 100644 docs/sensor-protocol.md delete mode 100644 docs/setup.md create mode 100644 examples/event-sources/amqp.yaml create mode 100644 examples/event-sources/artifact.yaml create mode 100644 examples/event-sources/aws-sns.yaml create mode 100644 examples/event-sources/aws-sqs.yaml create mode 100644 examples/event-sources/calendar.yaml create mode 100644 examples/event-sources/file.yaml create mode 100644 examples/event-sources/gcp-pubsub.yaml create mode 100644 examples/event-sources/github.yaml create mode 100644 examples/event-sources/gitlab.yaml rename examples/{gateways/hdfs-configmap.yaml => event-sources/hdfs.yaml} (78%) create mode 100644 examples/event-sources/kafka.yaml create mode 100644 examples/event-sources/mqtt.yaml create mode 100644 examples/event-sources/nats.yaml create mode 100644 examples/event-sources/resource.yaml create mode 100644 examples/event-sources/slack.yaml create mode 100644 examples/event-sources/storage-grid.yaml create mode 100644 examples/event-sources/webhook.yaml delete mode 100644 examples/gateways/amqp-gateway-configmap.yaml delete mode 100644 examples/gateways/artifact-gateway-configmap.yaml rename examples/gateways/{artifact-http.yaml => artifact.yaml} (76%) delete mode 100644 examples/gateways/aws-sns-gateway-configmap.yaml delete mode 100644 examples/gateways/aws-sqs-gateway-configmap.yaml delete mode 100644 examples/gateways/calendar-gateway-configmap.yaml delete mode 100644 examples/gateways/file-gateway-configmap.yaml delete mode 100644 examples/gateways/gcp-pubsub-gateway-configmap.yaml delete mode 100644 examples/gateways/github-gateway-configmap.yaml delete mode 100644 examples/gateways/gitlab-gateway-configmap.yaml delete mode 100644 examples/gateways/kafka-gateway-configmap.yaml delete mode 100644 examples/gateways/mqtt-gateway-configmap.yaml delete mode 100644 examples/gateways/nats-gateway-configmap.yaml delete mode 100644 examples/gateways/resource-gateway-configmap.yaml delete mode 100644 examples/gateways/secure-webhook-gateway-configmap.yaml delete mode 100644 examples/gateways/slack-gateway-configmap.yaml delete mode 100644 examples/gateways/storage-grid-gateway-configmap.yaml delete mode 100644 examples/gateways/trello-gateway-configmap.yaml delete mode 100644 examples/gateways/trello.yaml delete mode 100644 examples/gateways/webhook-gateway-configmap.yaml rename examples/gateways/{webhook-http.yaml => webhook.yaml} (54%) rename examples/sensors/{webhook-http-dependency-groups.yaml => dependencies-circuit-complex.yaml} (94%) rename examples/sensors/{webhook-http-boolean.yaml => dependencies-circuit.yaml} (90%) delete mode 100644 examples/sensors/trello.yaml rename examples/sensors/{file-sensor.yaml => trigger-source-file.yaml} (79%) rename examples/sensors/{trigger-backoff.yaml => trigger-with-backoff.yaml} (96%) delete mode 100644 examples/sensors/webhook-with-complete-payload.yaml delete mode 100644 examples/sensors/webhook-with-resource-param.yaml rename examples/sensors/{webhook-http.yaml => webhook.yaml} (84%) delete mode 100755 hack/e2e/cleanup-e2e.sh delete mode 100644 hack/e2e/manifests/argo-events-cluster-roles.yaml delete mode 100644 hack/e2e/manifests/argo-events-sa.yaml delete mode 100644 hack/e2e/manifests/gateway-controller-configmap.yaml mode change 100644 => 100755 hack/e2e/manifests/gateway-controller-deployment.yaml delete mode 100644 hack/e2e/manifests/sensor-controller-configmap.yaml mode change 100644 => 100755 hack/e2e/manifests/sensor-controller-deployment.yaml delete mode 100755 hack/e2e/run-e2e.sh create mode 100644 mkdocs.yml delete mode 100644 test/e2e/common/constants.go delete mode 100644 test/e2e/common/manifests/namespace.yaml delete mode 100644 test/e2e/common/manifests/rolebinding.yaml delete mode 100644 test/e2e/common/misc.go delete mode 100644 test/e2e/core/manifests/general-use-case/webhook-gateway-configmap.yaml create mode 100644 test/e2e/core/manifests/general-use-case/webhook-gateway-event-source.yaml diff --git a/.travis.yml b/.travis.yml index 908f8b86ed..48ca3f5e4e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ cache: env: global: - DOCKER_PUSH=false - - IMAGE_TAG=latest + - IMAGE_TAG=v0.10-test - PATH=$HOME/bin:$PATH before_install: diff --git a/Gopkg.lock b/Gopkg.lock index 9f22331acd..28fdf93af1 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -13,13 +13,13 @@ "pubsub/apiv1", "pubsub/internal/distribution" ] - revision = "a4ed3b9f8c7419c692a60bbf780ab0f1c4af5ce4" + revision = "e65d5a7bb2799d5dbfd6ca17030c94951454b08c" [[projects]] name = "github.com/DataDog/zstd" packages = ["."] - revision = "c7161f8c63c045cbc7ca051dcc969dd0e4054de2" - version = "v1.3.5" + revision = "69c5189b6513b1503c9c5332fb2e96362e51d547" + version = "v1.3.8" [[projects]] branch = "master" @@ -42,8 +42,8 @@ [[projects]] name = "github.com/Shopify/sarama" packages = ["."] - revision = "4602b5a8c6e826f9e0737865818dd43b2339a092" - version = "v1.21.0" + revision = "5d2af84cf5e2dd36f2daecaaafa13c4e286f20fd" + version = "v1.22.0" [[projects]] name = "github.com/argoproj/argo" @@ -90,7 +90,7 @@ "service/sqs", "service/sts" ] - revision = "3ef79e6ee13bcdb585ec75e207e349cde24ae8bc" + revision = "a59596beb512ad4327d1e109267224f01653d877" [[projects]] name = "github.com/colinmarc/hdfs" @@ -266,7 +266,7 @@ "ptypes/empty", "ptypes/timestamp" ] - revision = "d3c38a4eb4970272b87a425ae00ccc4548e2f9bb" + revision = "e91709a02e0e8ff8b86b7aa913fdc9ae9498e825" [[projects]] name = "github.com/golang/snappy" @@ -286,10 +286,10 @@ version = "v1.0.0" [[projects]] - branch = "master" name = "github.com/google/gofuzz" packages = ["."] - revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1" + revision = "f140a6486e521aad38f5917de355cbf147cc0496" + version = "v1.0.0" [[projects]] name = "github.com/googleapis/gax-go" @@ -311,7 +311,7 @@ branch = "master" name = "github.com/gopherjs/gopherjs" packages = ["js"] - revision = "bb2674552d8fc183605e16acbf9e8f0a0b031dee" + revision = "8a4e74d23f07f7bff3bc6a7378c7849807f278f6" [[projects]] name = "github.com/gorilla/websocket" @@ -471,8 +471,8 @@ [[projects]] name = "github.com/nats-io/nuid" packages = ["."] - revision = "289cccf02c178dc782430d534e3c1f5b72af807f" - version = "v1.0.0" + revision = "4b96681fa6d28dd0ab5fe79bac63b3a493d9ee94" + version = "v1.0.1" [[projects]] branch = "master" @@ -484,7 +484,7 @@ "slackevents", "slackutilsx" ] - revision = "490f287f4b4412bf56d2d176d640cb916d008371" + revision = "c33a46b52751322265b0e3f6243aaa462c738684" [[projects]] name = "github.com/pelletier/go-buffruneio" @@ -659,8 +659,8 @@ "trace/propagation", "trace/tracestate" ] - revision = "46618d076d80f4eab85adbcb3be9a370be1dc4e0" - version = "v0.20.0" + revision = "75c0cca22312e51bfd4fafdbe9197ae399e18b38" + version = "v0.20.2" [[projects]] branch = "master" @@ -738,7 +738,7 @@ "unix", "windows" ] - revision = "4b34438f7a67ee5f45cc6132e2bad873a20324e9" + revision = "cc4d4f50624c67f0af3a3fa307f4be9ab9030144" [[projects]] name = "golang.org/x/text" @@ -784,7 +784,7 @@ "internal/module", "internal/semver" ] - revision = "d996c1aa53b10c3c47e1764d087a569bb6c32ed1" + revision = "2538eef75904eff384a2551359968e40c207d9d2" [[projects]] name = "google.golang.org/api" @@ -799,8 +799,8 @@ "transport/http", "transport/http/internal/propagation" ] - revision = "bce707a4d0ea3488942724b3bcc1c8338f38f991" - version = "v0.3.0" + revision = "0cbcb99a9ea0c8023c794b2693cbe1def82ed4d7" + version = "v0.3.2" [[projects]] name = "google.golang.org/appengine" @@ -851,6 +851,7 @@ "grpclog", "internal", "internal/backoff", + "internal/balancerload", "internal/binarylog", "internal/channelz", "internal/envconfig", @@ -869,8 +870,8 @@ "status", "tap" ] - revision = "3507fb8e1a5ad030303c106fef3a47c9fdad16ad" - version = "v1.19.1" + revision = "236199dd5f8031d698fb64091194aecd1c3895b2" + version = "v1.20.0" [[projects]] name = "gopkg.in/inf.v0" diff --git a/README.md b/README.md index 9e6b68fcfb..b76640339c 100644 --- a/README.md +++ b/README.md @@ -33,105 +33,8 @@ and trigger Kubernetes objects after successful event dependencies resolution. * CloudEvents compliant. * Ability to manage event sources at runtime. -## Core Concepts -The framework is made up of two components: - - 1. **`Gateway`** which is implemented as a Kubernetes-native Custom Resource Definition processes events from event source. - - 2. **`Sensor`** which is implemented as a Kubernetes-native Custom Resource Definition defines a set of event dependencies and triggers K8s resources. - -## Install - -* ### Requirements - * Kubernetes cluster >v1.9 - * Installed the [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) command-line tool >v1.9.0 - -* ### Helm Chart - - Make sure you have helm client installed and Tiller server is running. To install helm, follow https://docs.helm.sh/using_helm/ - - 1. Add `argoproj` repository - - ```bash - helm repo add argo https://argoproj.github.io/argo-helm - ``` - - 2. Install `argo-events` chart - - ```bash - helm install argo/argo-events - ``` - -* ### Using kubectl - * Deploy Argo Events SA, Roles, ConfigMap, Sensor Controller and Gateway Controller - - ``` - kubectl create namespace argo-events - kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/argo-events-sa.yaml - kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/argo-events-cluster-roles.yaml - kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/sensor-crd.yaml - kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/gateway-crd.yaml - kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/sensor-controller-configmap.yaml - kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/sensor-controller-deployment.yaml - kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/gateway-controller-configmap.yaml - kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/gateway-controller-deployment.yaml - ``` - -**Note**: If you have already deployed the argo workflow controller in another namespace -and the controller is namespace scoped, make sure to deploy a new controller in `argo-events` namespace. - -## Get Started -Lets deploy a webhook gateway and sensor, - - * First, we need to setup event sources for gateway to listen. The event sources for any gateway are managed using K8s configmap. - - ```bash - kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/examples/gateways/webhook-gateway-configmap.yaml - ``` - - * Create webhook gateway, - - ```bash - kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/examples/gateways/webhook-http.yaml - ``` - - After running above command, gateway controller will create corresponding gateway pod and a LoadBalancing service. - - * Create webhook sensor, - - ```bash - kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/examples/sensors/webhook-http.yaml - ``` - - Once sensor resource is created, sensor controller will create corresponding sensor pod and a ClusterIP service. - - * Once the gateway and sensor pods are running, trigger the webhook via a http POST request to `/foo` endpoint. - Note: the `WEBHOOK_SERVICE_URL` will differ based on the Kubernetes cluster. - ``` - export WEBHOOK_SERVICE_URL=$(minikube service -n argo-events --url ) - echo $WEBHOOK_SERVICE_URL - curl -d '{"message":"this is my first webhook"}' -H "Content-Type: application/json" -X POST $WEBHOOK_SERVICE_URL/foo - ``` - - Note: - * If you are facing an issue getting service url by running `minikube service -n argo-events --url `, you can use `kubectl port-forward` - * Open another terminal window and enter `kubectl port-forward -n argo-events 9003:` - * You can now use `localhost:9003` to query webhook gateway - - Verify that the Argo workflow was run when the trigger was executed. - ``` - argo list -n argo-events - ``` - - * More examples can be found at [examples](./examples) - -## Further Reading -1. [Gateway](docs/gateway-guide.md) -2. [Sensor](docs/sensor-guide.md) -3. [Trigger](docs/trigger-guide.md) -4. [Communication between gateway and sensor](docs/communication.md) -5. [Controllers](docs/controllers-guide.md) -6. [Setup Gateways & Sensors](docs/setup.md) +## Documentation +To learn more about Argo Events, [go to complete documentation](docs/) ## Contribute Read and abide by the [Argo Events Code of Conduct](https://github.com/argoproj/argo-events/blob/master/CODE_OF_CONDUCT.md) diff --git a/ROADMAP.md b/ROADMAP.md index 192022a392..0dce477afe 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,9 +1,11 @@ # Roadmap ## Development Phase -- Boolean logic for event dependencies in sensor +- Add prometheus metrics collection - E2E testing +- Microsoft Azure Blob Gateway +- Microsoft Teams Gateway +- Document use-cases ## Idea Phase -- Use [hashicorp/go-getter](https://github.com/hashicorp/go-getter) for the `ArtifactReader` interface. - Add [Upspin](https://upspin.io/) as an `Artifact` file source. diff --git a/VERSION b/VERSION index 9a7d84f2a9..688abaae7a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.9 \ No newline at end of file +0.10 \ No newline at end of file diff --git a/common/common.go b/common/common.go index 35071cd111..305ec1a5d9 100644 --- a/common/common.go +++ b/common/common.go @@ -22,11 +22,7 @@ import ( ) const ( - // EnvVarKubeConfig is the path to the Kubernetes configuration - EnvVarKubeConfig = "KUBE_CONFIG" - // SuccessResponse for http request - SuccessResponse = "Success" // ErrorResponse for http request ErrorResponse = "Error" @@ -38,20 +34,29 @@ const ( // DefaultControllerNamespace is the default namespace where the sensor and gateways controllers are installed DefaultControllerNamespace = "argo-events" +) + +// ENV VARS +const ( + // EnvVarKubeConfig is the path to the Kubernetes configuration + EnvVarKubeConfig = "KUBE_CONFIG" // EnvVarDebugLog is the env var to turn on the debug mode for logging EnvVarDebugLog = "DEBUG_LOG" ) -// SENSOR CONTROLLER CONSTANTS +// LABELS const ( - // LabelSensorControllerName is the default deployment name of the sensor-controller - LabelSensorControllerName = "sensor-controller" + // LabelOperation is a label for an operation in framework + LabelOperation = "operation" - // SensorControllerConfigMapKey is the key in the configmap to retrieve sensor configuration from. - // Content encoding is expected to be YAML. - SensorControllerConfigMapKey = "config" + // LabelEventSource is label for event name + LabelEventSource = "event-source" +) +// SENSOR CONTROLLER CONSTANTS +const ( + // env variables constants //LabelKeySensorControllerInstanceID is the label which allows to separate application among multiple running sensor controllers. LabelKeySensorControllerInstanceID = sensor.FullName + "/sensor-controller-instanceid" @@ -64,6 +69,17 @@ const ( // EnvVarSensorControllerConfigMap is the name of the configmap to use for the sensor-controller EnvVarSensorControllerConfigMap = "SENSOR_CONFIG_MAP" + // labels constants + // LabelSensorControllerName is the default deployment name of the sensor-controller + LabelSensorControllerName = "sensor-controller" + + LabelArgoEventsSensorVersion = "argo-events-sensor-version" + + // SensorControllerConfigMapKey is the key in the configmap to retrieve sensor configuration from. + // Content encoding is expected to be YAML. + SensorControllerConfigMapKey = "config" + + // miscellaneous constants // AnnotationSensorResourceSpecHashName is the annotation of a sensor resource spec hash AnnotationSensorResourceSpecHashName = sensor.FullName + "/resource-spec-hash" ) @@ -82,21 +98,13 @@ const ( // LabelSensorName is label for sensor name LabelSensorName = "sensor-name" - // LabelOperation is a label for an operation in framework - LabelOperation = "operation" - - // LabelEventSource is label for event name - LabelEventSource = "event-source" - // EnvVarSensorControllerInstanceID is used to get sensor controller instance id EnvVarSensorControllerInstanceID = "SENSOR_CONTROLLER_INSTANCE_ID" ) -// GATEWAY CONSTANTS +// GATEWAY CONTROLLER CONSTANTS const ( - // LabelGatewayControllerName is the default deployment name of the gateway-controller-controller - LabelGatewayControllerName = "gateway-controller" - + // env variables // EnvVarGatewayControllerConfigMap contains name of the configmap to retrieve gateway-controller configuration from EnvVarGatewayControllerConfigMap = "GATEWAY_CONTROLLER_CONFIG_MAP" @@ -106,16 +114,16 @@ const ( // EnvVarGatewayControllerName is used to get name of gateway controller EnvVarGatewayControllerName = "GATEWAY_CONTROLLER_NAME" - // GatewayControllerConfigMapKey is the key in the configmap to retrieve gateway-controller configuration from. - // Content encoding is expected to be YAML. - GatewayControllerConfigMapKey = "config" - // EnvVarGatewayName refers env var for name of gateway EnvVarGatewayName = "GATEWAY_NAME" // EnvVarGatewayNamespace is namespace where gateway controller is deployed EnvVarGatewayNamespace = "GATEWAY_NAMESPACE" + // labels + // LabelGatewayControllerName is the default deployment name of the gateway-controller-controller + LabelGatewayControllerName = "gateway-controller" + //LabelKeyGatewayControllerInstanceID is the label which allows to separate application among multiple running gateway-controller controllers. LabelKeyGatewayControllerInstanceID = gateway.FullName + "/gateway-controller-instanceid" @@ -125,28 +133,35 @@ const ( // LabelGatewayName is the label for gateway name LabelGatewayName = "gateway-name" - // LabelGatewayEventSourceName is the label for a event source in gateway - LabelGatewayEventSourceName = "config-name" - - // LabelGatewayEventSourceID is the label for gateway configuration ID - LabelGatewayEventSourceID = "event-source-id" + // LabelArgoEventsGatewayVersion is the label for the gateway version + LabelArgoEventsGatewayVersion = "argo-events-gateway-version" // AnnotationGatewayResourceSpecHashName is the annotation of a gateway resource spec hash AnnotationGatewayResourceSpecHashName = gateway.FullName + "/resource-spec-hash" - // Server Connection Timeout, 10 seconds - ServerConnTimeout = 10 + // GatewayControllerConfigMapKey is the key in the configmap to retrieve gateway-controller configuration from. + // Content encoding is expected to be YAML. + GatewayControllerConfigMapKey = "config" ) -// Gateway client constants +// GATEWAY CONSTANTS const ( + // LabelGatewayEventSourceName is the label for a event source in gateway + LabelGatewayEventSourceName = "event-source-name" + + // LabelGatewayEventSourceID is the label for gateway configuration ID + LabelGatewayEventSourceID = "event-source-id" + + // LabelArgoEventsEventSourceVersion is the label for event source version + LabelArgoEventsEventSourceVersion = "argo-events-event-source-version" + // EnvVarGatewayEventSourceConfigMap is used to get map containing event sources to run in a gateway EnvVarGatewayEventSourceConfigMap = "GATEWAY_EVENT_SOURCE_CONFIG_MAP" -) -// Gateway server constants -const ( EnvVarGatewayServerPort = "GATEWAY_SERVER_PORT" + + // Server Connection Timeout, 10 seconds + ServerConnTimeout = 10 ) // CloudEvents constants diff --git a/common/events.go b/common/events.go index a45bbf037d..e1b338730d 100644 --- a/common/events.go +++ b/common/events.go @@ -17,11 +17,11 @@ limitations under the License. package common import ( - "k8s.io/client-go/kubernetes" "time" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" ) // K8sEventType is the type of event generated to indicate change in state of resource diff --git a/common/logger.go b/common/logger.go index 25d5ad6cff..3736e2314e 100644 --- a/common/logger.go +++ b/common/logger.go @@ -17,9 +17,8 @@ limitations under the License. package common import ( - "os" - "github.com/sirupsen/logrus" + "os" ) // Logger constants @@ -37,135 +36,27 @@ const ( LabelHTTPMethod = "http-method" LabelClientID = "client-id" LabelVersion = "version" - LabelError = "error" LabelTime = "time" LabelTriggerName = "trigger-name" ) -// ArgoEventsLogger is the logger for the framework -type ArgoEventsLogger struct { - *logrus.Logger -} - // NewArgoEventsLogger returns a new ArgoEventsLogger -func NewArgoEventsLogger() *ArgoEventsLogger { - logrus.SetOutput(os.Stdout) - logrus.SetLevel(logrus.InfoLevel) +func NewArgoEventsLogger() *logrus.Logger { + log := &logrus.Logger{ + Out: os.Stdout, + Level: logrus.InfoLevel, + Formatter: &logrus.TextFormatter{ + TimestampFormat: "2006-01-02 15:04:05", + FullTimestamp: true, + ForceColors: true, + QuoteEmptyFields: true, + }, + } debugMode, ok := os.LookupEnv(EnvVarDebugLog) if ok && debugMode == "true" { - logrus.SetLevel(logrus.DebugLevel) + log.SetLevel(logrus.DebugLevel) } - return &ArgoEventsLogger{ - logrus.StandardLogger(), - } -} - -// WithNamespace returns logger with namespace field set -func (a *ArgoEventsLogger) WithNamespace(namespace string) *ArgoEventsLogger { - a.WithField(LabelNamespace, namespace) - return a -} - -// WithGatewayControllerName returns logger with gateway controller name set -func (a *ArgoEventsLogger) WithGatewayControllerName(name string) *ArgoEventsLogger { - a.WithField(LabelGatewayControllerName, name) - return a -} - -// WithGatewayName returns the logger with gateway name set -func (a *ArgoEventsLogger) WithGatewayName(name string) *ArgoEventsLogger { - a.WithField(LabelGatewayName, name) - return a -} - -// WithSensorControllerName returns the logger with sensor controller name set -func (a *ArgoEventsLogger) WithSensorControllerName(name string) *ArgoEventsLogger { - a.WithField(LabelSensorControllerName, name) - return a -} - -// WithSensorName returns the logger with sensor name set -func (a *ArgoEventsLogger) WithSensorName(name string) *ArgoEventsLogger { - a.WithField(LabelSensorName, name) - return a -} - -// WithPhase returns the logger with phase set -func (a *ArgoEventsLogger) WithPhase(phase string) *ArgoEventsLogger { - a.WithField(LabelPhase, phase) - return a -} - -// WithInstanceId returns the logger with instance id set -func (a *ArgoEventsLogger) WithInstanceId(instanceId string) *ArgoEventsLogger { - a.WithField(LabelInstanceID, instanceId) - return a -} - -// WithPodName returns the logger with pod name set -func (a *ArgoEventsLogger) WithPodName(podName string) *ArgoEventsLogger { - a.WithField(LabelPodName, podName) - return a -} - -// WithServiceName returns the logger with service name set -func (a *ArgoEventsLogger) WithServiceName(svcName string) *ArgoEventsLogger { - a.WithField(LabelServiceName, svcName) - return a -} - -// WithEventSource returns the logger with event source set -func (a *ArgoEventsLogger) WithEventSource(name string) *ArgoEventsLogger { - a.WithField(LabelEventSource, name) - return a -} - -// WithEndpoint returns the logger with endpoint set -func (a *ArgoEventsLogger) WithEndpoint(endpoint string) *ArgoEventsLogger { - a.WithField(LabelEndpoint, endpoint) - return a -} - -// WithPort returns the logger with port set -func (a *ArgoEventsLogger) WithPort(port string) *ArgoEventsLogger { - a.WithField(LabelPort, port) - return a -} - -// WithURL returns the logger with url set -func (a *ArgoEventsLogger) WithURL(url string) *ArgoEventsLogger { - a.WithField(LabelURL, url) - return a -} - -// WithVersion returns the logger with version set -func (a *ArgoEventsLogger) WithVersion(version string) *ArgoEventsLogger { - a.WithField(LabelVersion, version) - return a -} - -// WithHTTPMethod returns the logger with http method set -func (a *ArgoEventsLogger) WithHTTPMethod(method string) *ArgoEventsLogger { - a.WithField(LabelHTTPMethod, method) - return a -} - -// WithError returns the logger with error set -func (a *ArgoEventsLogger) WithError(err error) *ArgoEventsLogger { - a.WithField(LabelError, err) - return a -} - -// WithTime returns the logger with time set -func (a *ArgoEventsLogger) WithTime(time string) *ArgoEventsLogger { - a.WithField(LabelTime, time) - return a -} - -// WithTrigger returns the logger with trigger name set -func (a *ArgoEventsLogger) WithTrigger(name string) *ArgoEventsLogger { - a.WithField(LabelTriggerName, name) - return a + return log } diff --git a/common/retry.go b/common/retry.go index 4b88922837..3c2ea15092 100644 --- a/common/retry.go +++ b/common/retry.go @@ -23,6 +23,14 @@ import ( "k8s.io/apimachinery/pkg/util/wait" ) +// Backoff defines an operational backoff +type Backoff struct { + Duration time.Duration `json:"duration"` // the base duration + Factor float64 `json:"factor"` // Duration is multiplied by factor each iteration + Jitter float64 `json:"jitter"` // The amount of jitter applied each iteration + Steps int `json:"steps"` // Exit with error after this many steps +} + // DefaultRetry is a default retry backoff settings when retrying API calls var DefaultRetry = wait.Backoff{ Steps: 5, diff --git a/common/util.go b/common/util.go index 20562a7df6..c9aea6304d 100644 --- a/common/util.go +++ b/common/util.go @@ -22,6 +22,7 @@ import ( "hash/fnv" "net/http" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/discovery" @@ -104,3 +105,13 @@ func GetObjectHash(obj metav1.Object) (string, error) { } return Hasher(string(b)), nil } + +func CheckEventSourceVersion(cm *corev1.ConfigMap) error { + if cm.Labels == nil { + return fmt.Errorf("labels can't be empty. event source must be specified in as %s label", LabelArgoEventsEventSourceVersion) + } + if _, ok := cm.Labels[LabelArgoEventsEventSourceVersion]; !ok { + return fmt.Errorf("event source must be specified in as %s label", LabelArgoEventsEventSourceVersion) + } + return nil +} diff --git a/controllers/gateway/config.go b/controllers/gateway/config.go index 5fbc6396d6..9dddaf0518 100644 --- a/controllers/gateway/config.go +++ b/controllers/gateway/config.go @@ -41,7 +41,7 @@ func (c *GatewayController) watchControllerConfigMap(ctx context.Context) (cache cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { if cm, ok := obj.(*apiv1.ConfigMap); ok { - c.log.Info("detected ConfigMap update. updating the gateway-controller config.") + c.log.Info("detected EventSource update. updating the gateway-controller config.") err := c.updateConfig(cm) if err != nil { c.log.Error("update of config failed", "err", err) @@ -50,10 +50,10 @@ func (c *GatewayController) watchControllerConfigMap(ctx context.Context) (cache }, UpdateFunc: func(old, new interface{}) { if newCm, ok := new.(*apiv1.ConfigMap); ok { - c.log.Info("detected ConfigMap update. updating the gateway-controller config.") + c.log.Info("detected EventSource update. updating the gateway-controller config.") err := c.updateConfig(newCm) if err != nil { - c.log.Errorf("update of config failed", "err", err) + c.log.WithError(err).Error("update of config failed") } } }, diff --git a/controllers/gateway/controller.go b/controllers/gateway/controller.go index 57c732b0b1..6177283158 100644 --- a/controllers/gateway/controller.go +++ b/controllers/gateway/controller.go @@ -20,6 +20,7 @@ import ( "context" "errors" "fmt" + "github.com/sirupsen/logrus" "time" base "github.com/argoproj/argo-events" @@ -56,14 +57,14 @@ type GatewayControllerConfig struct { // GatewayController listens for new gateways and hands off handling of each gateway-controller on the queue to the operator type GatewayController struct { - // ConfigMap is the name of the config map in which to derive configuration of the contoller + // EventSource is the name of the config map in which to derive configuration of the contoller ConfigMap string // Namespace for gateway controller Namespace string // Config is the gateway-controller gateway-controller-controller's configuration Config GatewayControllerConfig // log is the logger for a gateway - log *common.ArgoEventsLogger + log *logrus.Logger // kubernetes config and apis kubeConfig *rest.Config @@ -101,7 +102,7 @@ func (c *GatewayController) processNextItem() bool { obj, exists, err := c.informer.GetIndexer().GetByKey(key.(string)) if err != nil { - c.log.WithGatewayName(key.(string)).WithError(err).Warn("failed to get gateway '%s' from informer index") + c.log.WithField(common.LabelGatewayName, key.(string)).WithError(err).Warn("failed to get gateway from informer index") return true } @@ -110,26 +111,26 @@ func (c *GatewayController) processNextItem() bool { return true } - gateway, ok := obj.(*v1alpha1.Gateway) + gw, ok := obj.(*v1alpha1.Gateway) if !ok { - c.log.WithGatewayName(key.(string)).WithError(err).Warn("key in index is not a gateway") + c.log.WithField(common.LabelGatewayName, key.(string)).WithError(err).Warn("key in index is not a gateway") return true } - ctx := newGatewayOperationCtx(gateway, c) + ctx := newGatewayOperationCtx(gw, c) err = ctx.operate() if err != nil { if err := common.GenerateK8sEvent(c.kubeClientset, - fmt.Sprintf("controller failed to operate on gateway %s", gateway.Name), + fmt.Sprintf("controller failed to operate on gateway %s", gw.Name), common.StateChangeEventType, "controller operation failed", - gateway.Name, - gateway.Namespace, + gw.Name, + gw.Namespace, c.Config.InstanceID, - gateway.Kind, + gw.Kind, map[string]string{ - common.LabelGatewayName: gateway.Name, + common.LabelGatewayName: gw.Name, common.LabelEventType: string(common.EscalationEventType), }, ); err != nil { @@ -159,7 +160,7 @@ func (c *GatewayController) handleErr(err error, key interface{}) error { // requeues will happen very quickly even after a gateway pod goes down // we want to give the event pod a chance to come back up so we give a generous number of retries if c.queue.NumRequeues(key) < 20 { - c.log.WithGatewayName(key.(string)).WithError(err).Error("error syncing gateway") + c.log.WithField(common.LabelGatewayName, key.(string)).WithError(err).Error("error syncing gateway") // Re-enqueue the key rate limited. This key will be processed later again. c.queue.AddRateLimited(key) @@ -171,7 +172,11 @@ func (c *GatewayController) handleErr(err error, key interface{}) error { // Run executes the gateway-controller func (c *GatewayController) Run(ctx context.Context, gwThreads, eventThreads int) { defer c.queue.ShutDown() - c.log.WithInstanceId(c.Config.InstanceID).WithVersion(base.GetVersion().Version).Infof("starting gateway-controller") + c.log.WithFields( + map[string]interface{}{ + common.LabelInstanceID: c.Config.InstanceID, + common.LabelVersion: base.GetVersion().Version, + }).Info("starting gateway-controller") _, err := c.watchControllerConfigMap(ctx) if err != nil { c.log.WithError(err).Error("failed to register watch for gateway-controller config map") diff --git a/controllers/gateway/informer.go b/controllers/gateway/informer.go index 608156160e..e555f87ed2 100644 --- a/controllers/gateway/informer.go +++ b/controllers/gateway/informer.go @@ -17,6 +17,7 @@ limitations under the License. package gateway import ( + "github.com/argoproj/argo-events/pkg/apis/gateway/v1alpha1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" @@ -28,19 +29,25 @@ import ( ) func (c *GatewayController) instanceIDReq() labels.Requirement { - var instanceIDReq *labels.Requirement - var err error // it makes sense to make instance id is mandatory. if c.Config.InstanceID == "" { panic("instance id is required") } - instanceIDReq, err = labels.NewRequirement(common.LabelKeyGatewayControllerInstanceID, selection.Equals, []string{c.Config.InstanceID}) + instanceIDReq, err := labels.NewRequirement(common.LabelKeyGatewayControllerInstanceID, selection.Equals, []string{c.Config.InstanceID}) if err != nil { panic(err) } return *instanceIDReq } +func (c *GatewayController) versionReq() labels.Requirement { + versionReq, err := labels.NewRequirement(common.LabelArgoEventsGatewayVersion, selection.Equals, []string{v1alpha1.ArgoEventsGatewayVersion}) + if err != nil { + panic(err) + } + return *versionReq +} + // The gateway-controller informer adds new Gateways to the gateway-controller-controller's queue based on Add, Update, and Delete Event Handlers for the Gateway Resources func (c *GatewayController) newGatewayInformer() cache.SharedIndexInformer { gatewayInformerFactory := gatewayinformers.NewFilteredSharedInformerFactory( @@ -49,7 +56,7 @@ func (c *GatewayController) newGatewayInformer() cache.SharedIndexInformer { c.Config.Namespace, func(options *metav1.ListOptions) { options.FieldSelector = fields.Everything().String() - labelSelector := labels.NewSelector().Add(c.instanceIDReq()) + labelSelector := labels.NewSelector().Add(c.instanceIDReq(), c.versionReq()) options.LabelSelector = labelSelector.String() }, ) diff --git a/controllers/gateway/operator.go b/controllers/gateway/operator.go index 8cbd4743cb..da890be6f4 100644 --- a/controllers/gateway/operator.go +++ b/controllers/gateway/operator.go @@ -17,6 +17,7 @@ limitations under the License. package gateway import ( + "github.com/sirupsen/logrus" "time" "github.com/pkg/errors" @@ -36,7 +37,7 @@ type gwOperationCtx struct { // updated indicates whether the gateway-controller object was updated and needs to be persisted back to k8 updated bool // log is the logger for a gateway - log *common.ArgoEventsLogger + log *logrus.Logger // reference to the gateway-controller-controller controller *GatewayController // gwrctx is the context to handle child resource @@ -47,9 +48,13 @@ type gwOperationCtx struct { func newGatewayOperationCtx(gw *v1alpha1.Gateway, controller *GatewayController) *gwOperationCtx { gw = gw.DeepCopy() return &gwOperationCtx{ - gw: gw, - updated: false, - log: common.NewArgoEventsLogger().WithGatewayName(gw.Name).WithNamespace(gw.Namespace), + gw: gw, + updated: false, + log: common.NewArgoEventsLogger().WithFields( + map[string]interface{}{ + common.LabelGatewayName: gw.Name, + common.LabelNamespace: gw.Namespace, + }).Logger, controller: controller, gwrctx: NewGatewayResourceContext(gw, controller), } @@ -93,7 +98,7 @@ func (goc *gwOperationCtx) operate() error { goc.updated = false }() - goc.log.WithPhase(string(goc.gw.Status.Phase)).Info("operating on the gateway") + goc.log.WithField(common.LabelPhase, string(goc.gw.Status.Phase)).Info("operating on the gateway") // check the state of a gateway and take actions accordingly switch goc.gw.Status.Phase { @@ -120,7 +125,7 @@ func (goc *gwOperationCtx) operate() error { } default: - goc.log.WithPhase(string(goc.gw.Status.Phase)).Panic("unknown gateway phase.") + goc.log.WithField(common.LabelPhase, string(goc.gw.Status.Phase)).Panic("unknown gateway phase.") } return nil } @@ -143,7 +148,7 @@ func (goc *gwOperationCtx) createGatewayResources() error { goc.markGatewayPhase(v1alpha1.NodePhaseError, err.Error()) return err } - goc.log.WithPodName(pod.Name).Info("gateway pod is created") + goc.log.WithField(common.LabelPodName, pod.Name).Info("gateway pod is created") // expose gateway if service is configured if goc.gw.Spec.Service != nil { @@ -153,7 +158,7 @@ func (goc *gwOperationCtx) createGatewayResources() error { goc.markGatewayPhase(v1alpha1.NodePhaseError, err.Error()) return err } - goc.log.WithServiceName(svc.Name).Info("gateway service is created") + goc.log.WithField(common.LabelServiceName, svc.Name).Info("gateway service is created") } goc.log.Info("marking gateway as active") @@ -239,12 +244,12 @@ func (goc *gwOperationCtx) updateGatewayPod() (*corev1.Pod, bool, error) { // check if pod spec remained unchanged if existingPod != nil { if existingPod.Annotations != nil && existingPod.Annotations[common.AnnotationGatewayResourceSpecHashName] == newPod.Annotations[common.AnnotationGatewayResourceSpecHashName] { - goc.log.WithPodName(existingPod.Name).Debug("gateway pod spec unchanged") + goc.log.WithField(common.LabelPodName, existingPod.Name).Debug("gateway pod spec unchanged") return nil, false, nil } // By now we are sure that the spec changed, so lets go ahead and delete the exisitng gateway pod. - goc.log.WithPodName(existingPod.Name).Info("gateway pod spec changed") + goc.log.WithField(common.LabelPodName, existingPod.Name).Info("gateway pod spec changed") err := goc.gwrctx.deleteGatewayPod(existingPod) if err != nil { @@ -252,7 +257,7 @@ func (goc *gwOperationCtx) updateGatewayPod() (*corev1.Pod, bool, error) { return nil, false, err } - goc.log.WithPodName(existingPod.Name).Info("gateway pod is deleted") + goc.log.WithField(common.LabelPodName, existingPod.Name).Info("gateway pod is deleted") } // Create new pod for updated gateway spec. @@ -261,7 +266,7 @@ func (goc *gwOperationCtx) updateGatewayPod() (*corev1.Pod, bool, error) { goc.log.WithError(err).Error("failed to create pod for gateway") return nil, false, err } - goc.log.WithError(err).WithPodName(newPod.Name).Info("gateway pod is created") + goc.log.WithError(err).WithField(common.LabelPodName, newPod.Name).Info("gateway pod is created") return createdPod, true, nil } @@ -292,12 +297,12 @@ func (goc *gwOperationCtx) updateGatewayService() (*corev1.Service, bool, error) // check if service spec remained unchanged if existingSvc.Annotations[common.AnnotationGatewayResourceSpecHashName] == newSvc.Annotations[common.AnnotationGatewayResourceSpecHashName] { - goc.log.WithServiceName(existingSvc.Name).Debug("gateway service spec unchanged") + goc.log.WithField(common.LabelServiceName, existingSvc.Name).Debug("gateway service spec unchanged") return nil, false, nil } // service spec changed, delete existing service and create new one - goc.log.WithServiceName(existingSvc.Name).Info("gateway service spec changed") + goc.log.WithField(common.LabelServiceName, existingSvc.Name).Info("gateway service spec changed") if err := goc.gwrctx.deleteGatewayService(existingSvc); err != nil { return nil, false, err @@ -313,7 +318,7 @@ func (goc *gwOperationCtx) updateGatewayService() (*corev1.Service, bool, error) goc.log.WithError(err).Error("failed to create service for gateway") return nil, false, err } - goc.log.WithServiceName(createdSvc.Name).Info("gateway service is created") + goc.log.WithField(common.LabelServiceName, createdSvc.Name).Info("gateway service is created") return createdSvc, true, nil } diff --git a/controllers/gateway/operator_test.go b/controllers/gateway/operator_test.go index 2e22fe8b3e..710bd3b979 100644 --- a/controllers/gateway/operator_test.go +++ b/controllers/gateway/operator_test.go @@ -35,8 +35,9 @@ metadata: labels: gateways.argoproj.io/gateway-controller-instanceid: argo-events gateway-name: "webhook-gateway" + argo-events-gateway-version: v0.10 spec: - configMap: "webhook-gateway-configmap" + eventSource: "webhook-gateway-configmap" type: "webhook" processorPort: "9330" eventProtocol: diff --git a/controllers/gateway/resource.go b/controllers/gateway/resource.go index 76dca573a0..4f59d794c2 100644 --- a/controllers/gateway/resource.go +++ b/controllers/gateway/resource.go @@ -143,7 +143,7 @@ func (grc *gwResourceCtx) setupContainersForGatewayPod(pod *corev1.Pod) { }, { Name: common.EnvVarGatewayEventSourceConfigMap, - Value: grc.gw.Spec.ConfigMap, + Value: grc.gw.Spec.EventSource, }, { Name: common.EnvVarGatewayName, diff --git a/controllers/gateway/state.go b/controllers/gateway/state.go index 98e3926de4..7c61b47580 100644 --- a/controllers/gateway/state.go +++ b/controllers/gateway/state.go @@ -4,12 +4,13 @@ import ( "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/pkg/apis/gateway/v1alpha1" gwclient "github.com/argoproj/argo-events/pkg/client/gateway/clientset/versioned" + "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/util/wait" ) // PersistUpdates of the gateway resource -func PersistUpdates(client gwclient.Interface, gw *v1alpha1.Gateway, log *common.ArgoEventsLogger) (*v1alpha1.Gateway, error) { +func PersistUpdates(client gwclient.Interface, gw *v1alpha1.Gateway, log *logrus.Logger) (*v1alpha1.Gateway, error) { gatewayClient := client.ArgoprojV1alpha1().Gateways(gw.ObjectMeta.Namespace) // in case persist update fails @@ -28,7 +29,7 @@ func PersistUpdates(client gwclient.Interface, gw *v1alpha1.Gateway, log *common return oldgw, err } } - log.WithError(err).WithPhase(string(gw.Status.Phase)).Info("gateway state updated successfully") + log.WithField(common.LabelPhase, string(gw.Status.Phase)).Info("gateway state updated successfully") return gw, nil } diff --git a/controllers/gateway/validate.go b/controllers/gateway/validate.go index 5a8fe495d9..73860ff8a2 100644 --- a/controllers/gateway/validate.go +++ b/controllers/gateway/validate.go @@ -31,9 +31,13 @@ func Validate(gw *v1alpha1.Gateway) error { if gw.Spec.Type == "" { return fmt.Errorf("gateway type is not specified") } - if gw.Spec.EventVersion == "" { - return fmt.Errorf("gateway version is not specified") + if gw.Spec.EventSource == "" { + return fmt.Errorf("event source for the gateway is not specified") } + if gw.Spec.ProcessorPort == "" { + return fmt.Errorf("gateway processor port is not specified") + } + switch gw.Spec.EventProtocol.Type { case apicommon.HTTP: if gw.Spec.Watchers == nil || (gw.Spec.Watchers.Gateways == nil && gw.Spec.Watchers.Sensors == nil) { diff --git a/controllers/gateway/validate_test.go b/controllers/gateway/validate_test.go index 85843b0dc3..47631c1dcb 100644 --- a/controllers/gateway/validate_test.go +++ b/controllers/gateway/validate_test.go @@ -21,7 +21,6 @@ import ( "github.com/argoproj/argo-events/pkg/apis/gateway/v1alpha1" "github.com/ghodss/yaml" "io/ioutil" - "strings" "testing" "github.com/smartystreets/goconvey/convey" @@ -33,9 +32,6 @@ func TestValidate(t *testing.T) { files, err := ioutil.ReadDir(dir) convey.So(err, convey.ShouldBeNil) for _, file := range files { - if strings.HasSuffix(file.Name(), "configmap.yaml") { - continue - } fmt.Println("filename: ", file.Name()) content, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", dir, file.Name())) convey.So(err, convey.ShouldBeNil) diff --git a/controllers/sensor/config.go b/controllers/sensor/config.go index 1f0a75719d..2515e6c838 100644 --- a/controllers/sensor/config.go +++ b/controllers/sensor/config.go @@ -19,8 +19,8 @@ package sensor import ( "context" "fmt" - "github.com/argoproj/argo-events/common" + "github.com/ghodss/yaml" log "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" @@ -42,7 +42,7 @@ func (c *SensorController) watchControllerConfigMap(ctx context.Context) (cache. cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { if cm, ok := obj.(*corev1.ConfigMap); ok { - log.Info("detected ConfigMap update. updating the sensor-controller config.") + log.Info("detected EventSource update. updating the sensor-controller config.") err := c.updateConfig(cm) if err != nil { log.Errorf("update of config failed due to: %v", err) @@ -51,7 +51,7 @@ func (c *SensorController) watchControllerConfigMap(ctx context.Context) (cache. }, UpdateFunc: func(old, new interface{}) { if newCm, ok := new.(*corev1.ConfigMap); ok { - log.Info("detected ConfigMap update. updating the sensor-controller config.") + log.Info("detected EventSource update. updating the sensor-controller config.") err := c.updateConfig(newCm) if err != nil { log.Errorf("update of config failed due to: %v", err) diff --git a/controllers/sensor/controller.go b/controllers/sensor/controller.go index 4d16b72572..edf99cbfd1 100644 --- a/controllers/sensor/controller.go +++ b/controllers/sensor/controller.go @@ -20,6 +20,8 @@ import ( "context" "errors" "fmt" + "github.com/argoproj/argo-events/pkg/apis/sensor" + "github.com/sirupsen/logrus" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -39,6 +41,7 @@ import ( clientset "github.com/argoproj/argo-events/pkg/client/sensor/clientset/versioned" ) +// informer constants const ( sensorResyncPeriod = 20 * time.Minute sensorResourceResyncPeriod = 30 * time.Minute @@ -58,14 +61,14 @@ type SensorControllerConfig struct { // SensorController listens for new sensors and hands off handling of each sensor on the queue to the operator type SensorController struct { - // ConfigMap is the name of the config map in which to derive configuration of the contoller + // EventSource is the name of the config map in which to derive configuration of the contoller ConfigMap string // Namespace for sensor controller Namespace string // Config is the sensor-controller's configuration Config SensorControllerConfig // log is the logger for a gateway - log *common.ArgoEventsLogger + log *logrus.Logger // kubernetes config and apis kubeConfig *rest.Config @@ -89,7 +92,7 @@ func NewSensorController(rest *rest.Config, configMap, namespace string) *Sensor kubeClientset: kubernetes.NewForConfigOrDie(rest), sensorClientset: clientset.NewForConfigOrDie(rest), queue: workqueue.NewRateLimitingQueue(rateLimiter), - log: common.NewArgoEventsLogger().WithNamespace(namespace), + log: common.NewArgoEventsLogger(), } } @@ -103,7 +106,7 @@ func (c *SensorController) processNextItem() bool { obj, exists, err := c.informer.GetIndexer().GetByKey(key.(string)) if err != nil { - c.log.WithSensorName(key.(string)).WithError(err).Warn("failed to get sensor from informer index") + c.log.WithField(common.LabelSensorName, key.(string)).WithError(err).Warn("failed to get sensor from informer index") return true } @@ -112,26 +115,26 @@ func (c *SensorController) processNextItem() bool { return true } - sensor, ok := obj.(*v1alpha1.Sensor) + s, ok := obj.(*v1alpha1.Sensor) if !ok { - c.log.WithSensorName(key.(string)).WithError(err).Warn("key in index is not a sensor") + c.log.WithField(common.LabelSensorName, key.(string)).WithError(err).Warn("key in index is not a sensor") return true } - ctx := newSensorOperationCtx(sensor, c) + ctx := newSensorOperationCtx(s, c) err = ctx.operate() if err != nil { if err := common.GenerateK8sEvent(c.kubeClientset, - fmt.Sprintf("failed to operate on sensor %s", sensor.Name), + fmt.Sprintf("failed to operate on sensor %s", s.Name), common.EscalationEventType, "sensor operation failed", - sensor.Name, - sensor.Namespace, + s.Name, + s.Namespace, c.Config.InstanceID, sensor.Kind, map[string]string{ - common.LabelSensorName: sensor.Name, + common.LabelSensorName: s.Name, common.LabelEventType: string(common.EscalationEventType), common.LabelOperation: "controller_operation", }, @@ -172,7 +175,11 @@ func (c *SensorController) handleErr(err error, key interface{}) error { func (c *SensorController) Run(ctx context.Context, ssThreads, eventThreads int) { defer c.queue.ShutDown() - c.log.WithInstanceId(c.Config.InstanceID).WithVersion(base.GetVersion().Version).Info("starting sensor controller") + c.log.WithFields( + map[string]interface{}{ + common.LabelInstanceID: c.Config.InstanceID, + common.LabelVersion: base.GetVersion().Version, + }).Info("starting sensor controller") _, err := c.watchControllerConfigMap(ctx) if err != nil { c.log.WithError(err).Error("failed to register watch for sensor controller config map") diff --git a/controllers/sensor/informer.go b/controllers/sensor/informer.go index 9cb92e12ed..7965c6bb74 100644 --- a/controllers/sensor/informer.go +++ b/controllers/sensor/informer.go @@ -17,12 +17,13 @@ limitations under the License. package sensor import ( + "github.com/argoproj/argo-events/common" + "github.com/argoproj/argo-events/pkg/apis/sensor/v1alpha1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" - "github.com/argoproj/argo-events/common" sensorinformers "github.com/argoproj/argo-events/pkg/client/sensor/informers/externalversions" "k8s.io/apimachinery/pkg/selection" ) @@ -40,6 +41,14 @@ func (c *SensorController) instanceIDReq() labels.Requirement { return *instanceIDReq } +func (c *SensorController) versionReq() labels.Requirement { + versionReq, err := labels.NewRequirement(common.LabelArgoEventsSensorVersion, selection.Equals, []string{v1alpha1.ArgoEventsSensorVersion}) + if err != nil { + panic(err) + } + return *versionReq +} + // The sensor informer adds new Sensors to the sensor-controller's queue based on Add, Update, and Delete Event Handlers for the Sensor Resources func (c *SensorController) newSensorInformer() cache.SharedIndexInformer { sensorInformerFactory := sensorinformers.NewFilteredSharedInformerFactory( @@ -48,7 +57,7 @@ func (c *SensorController) newSensorInformer() cache.SharedIndexInformer { c.Config.Namespace, func(options *metav1.ListOptions) { options.FieldSelector = fields.Everything().String() - labelSelector := labels.NewSelector().Add(c.instanceIDReq()) + labelSelector := labels.NewSelector().Add(c.instanceIDReq(), c.versionReq()) options.LabelSelector = labelSelector.String() }, ) diff --git a/controllers/sensor/informer_test.go b/controllers/sensor/informer_test.go index 2cda7bbc9f..75a5a8042e 100644 --- a/controllers/sensor/informer_test.go +++ b/controllers/sensor/informer_test.go @@ -17,9 +17,9 @@ limitations under the License. package sensor import ( + "github.com/argoproj/argo-events/common" "testing" - "github.com/argoproj/argo-events/common" "github.com/smartystreets/goconvey/convey" "k8s.io/apimachinery/pkg/selection" ) diff --git a/controllers/sensor/operator.go b/controllers/sensor/operator.go index 3bc9d3d498..99c058cd8c 100644 --- a/controllers/sensor/operator.go +++ b/controllers/sensor/operator.go @@ -17,6 +17,7 @@ limitations under the License. package sensor import ( + "github.com/sirupsen/logrus" "time" "github.com/pkg/errors" @@ -36,7 +37,7 @@ type sOperationCtx struct { // updated indicates whether the sensor object was updated and needs to be persisted back to k8 updated bool // log is the logrus logging context to correlate logs with a sensor - log *common.ArgoEventsLogger + log *logrus.Logger // reference to the sensor-controller controller *SensorController // srctx is the context to handle child resource @@ -46,9 +47,13 @@ type sOperationCtx struct { // newSensorOperationCtx creates and initializes a new sOperationCtx object func newSensorOperationCtx(s *v1alpha1.Sensor, controller *SensorController) *sOperationCtx { return &sOperationCtx{ - s: s.DeepCopy(), - updated: false, - log: common.NewArgoEventsLogger().WithSensorName(s.Name).WithNamespace(s.Namespace), + s: s.DeepCopy(), + updated: false, + log: common.NewArgoEventsLogger().WithFields( + map[string]interface{}{ + common.LabelSensorName: s.Name, + common.LabelNamespace: s.Namespace, + }).Logger, controller: controller, srctx: NewSensorResourceContext(s, controller), } @@ -139,7 +144,7 @@ func (soc *sOperationCtx) createSensorResources() error { return err } soc.markAllNodePhases() - soc.log.WithPodName(pod.Name).Info("sensor pod is created") + soc.log.WithField(common.LabelPodName, pod.Name).Info("sensor pod is created") // expose sensor if service is configured if soc.srctx.getServiceTemplateSpec() != nil { @@ -149,7 +154,7 @@ func (soc *sOperationCtx) createSensorResources() error { soc.markSensorPhase(v1alpha1.NodePhaseError, false, err.Error()) return err } - soc.log.WithServiceName(svc.Name).Info("sensor service is created") + soc.log.WithField(common.LabelServiceName, svc.Name).Info("sensor service is created") } // if we get here - we know the signals are running @@ -236,12 +241,12 @@ func (soc *sOperationCtx) updateSensorPod() (*corev1.Pod, bool, error) { // check if pod spec remained unchanged if existingPod != nil { if existingPod.Annotations != nil && existingPod.Annotations[common.AnnotationSensorResourceSpecHashName] == newPod.Annotations[common.AnnotationSensorResourceSpecHashName] { - soc.log.WithPodName(existingPod.Name).Debug("sensor pod spec unchanged") + soc.log.WithField(common.LabelPodName, existingPod.Name).Debug("sensor pod spec unchanged") return nil, false, nil } // By now we are sure that the spec changed, so lets go ahead and delete the exisitng sensor pod. - soc.log.WithPodName(existingPod.Name).Info("sensor pod spec changed") + soc.log.WithField(common.LabelPodName, existingPod.Name).Info("sensor pod spec changed") err := soc.srctx.deleteSensorPod(existingPod) if err != nil { @@ -249,7 +254,7 @@ func (soc *sOperationCtx) updateSensorPod() (*corev1.Pod, bool, error) { return nil, false, err } - soc.log.WithPodName(existingPod.Name).Info("sensor pod is deleted") + soc.log.WithField(common.LabelPodName, existingPod.Name).Info("sensor pod is deleted") } // Create new pod for updated sensor spec. @@ -258,7 +263,7 @@ func (soc *sOperationCtx) updateSensorPod() (*corev1.Pod, bool, error) { soc.log.WithError(err).Error("failed to create pod for sensor") return nil, false, err } - soc.log.WithPodName(newPod.Name).Info("sensor pod is created") + soc.log.WithField(common.LabelPodName, newPod.Name).Info("sensor pod is created") return createdPod, true, nil } @@ -289,12 +294,12 @@ func (soc *sOperationCtx) updateSensorService() (*corev1.Service, bool, error) { // check if service spec remained unchanged if existingSvc.Annotations[common.AnnotationSensorResourceSpecHashName] == newSvc.Annotations[common.AnnotationSensorResourceSpecHashName] { - soc.log.WithServiceName(existingSvc.Name).Debug("sensor service spec unchanged") + soc.log.WithField(common.LabelServiceName, existingSvc.Name).Debug("sensor service spec unchanged") return nil, false, nil } // service spec changed, delete existing service and create new one - soc.log.WithServiceName(existingSvc.Name).Info("sensor service spec changed") + soc.log.WithField(common.LabelServiceName, existingSvc.Name).Info("sensor service spec changed") if err := soc.srctx.deleteSensorService(existingSvc); err != nil { return nil, false, err @@ -307,10 +312,10 @@ func (soc *sOperationCtx) updateSensorService() (*corev1.Service, bool, error) { // change createSensorService to take a service spec createdSvc, err := soc.srctx.createSensorService(newSvc) if err != nil { - soc.log.WithServiceName(newSvc.Name).WithError(err).Error("failed to create service for sensor") + soc.log.WithField(common.LabelServiceName, newSvc.Name).WithError(err).Error("failed to create service for sensor") return nil, false, err } - soc.log.WithServiceName(newSvc.Name).Info("sensor service is created") + soc.log.WithField(common.LabelServiceName, newSvc.Name).Info("sensor service is created") return createdSvc, true, nil } diff --git a/controllers/sensor/state.go b/controllers/sensor/state.go index fac758cadc..d66584742a 100644 --- a/controllers/sensor/state.go +++ b/controllers/sensor/state.go @@ -18,6 +18,7 @@ package sensor import ( "github.com/argoproj/argo-events/pkg/apis/sensor/v1alpha1" + "github.com/sirupsen/logrus" "time" "github.com/argoproj/argo-events/common" @@ -40,7 +41,7 @@ func GetNodeByName(sensor *v1alpha1.Sensor, nodeName string) *v1alpha1.NodeStatu } // create a new node -func InitializeNode(sensor *v1alpha1.Sensor, nodeName string, nodeType v1alpha1.NodeType, log *common.ArgoEventsLogger, messages ...string) *v1alpha1.NodeStatus { +func InitializeNode(sensor *v1alpha1.Sensor, nodeName string, nodeType v1alpha1.NodeType, log *logrus.Logger, messages ...string) *v1alpha1.NodeStatus { if sensor.Status.Nodes == nil { sensor.Status.Nodes = make(map[string]v1alpha1.NodeStatus) } @@ -73,7 +74,7 @@ func InitializeNode(sensor *v1alpha1.Sensor, nodeName string, nodeType v1alpha1. } // PersistUpdates persists the updates to the Sensor resource -func PersistUpdates(client sclient.Interface, sensor *v1alpha1.Sensor, controllerInstanceId string, log *common.ArgoEventsLogger) (*v1alpha1.Sensor, error) { +func PersistUpdates(client sclient.Interface, sensor *v1alpha1.Sensor, controllerInstanceId string, log *logrus.Logger) (*v1alpha1.Sensor, error) { sensorClient := client.ArgoprojV1alpha1().Sensors(sensor.ObjectMeta.Namespace) // in case persist update fails oldsensor := sensor.DeepCopy() @@ -92,7 +93,7 @@ func PersistUpdates(client sclient.Interface, sensor *v1alpha1.Sensor, controlle return oldsensor, err } } - log.WithPhase(string(sensor.Status.Phase)).Info("sensor state updated successfully") + log.WithField(common.LabelPhase, string(sensor.Status.Phase)).Info("sensor state updated successfully") return sensor, nil } @@ -113,7 +114,7 @@ func ReapplyUpdate(sensorClient sclient.Interface, sensor *v1alpha1.Sensor) erro } // MarkNodePhase marks the node with a phase, returns the node -func MarkNodePhase(sensor *v1alpha1.Sensor, nodeName string, nodeType v1alpha1.NodeType, phase v1alpha1.NodePhase, event *apicommon.Event, log *common.ArgoEventsLogger, message ...string) *v1alpha1.NodeStatus { +func MarkNodePhase(sensor *v1alpha1.Sensor, nodeName string, nodeType v1alpha1.NodeType, phase v1alpha1.NodePhase, event *apicommon.Event, log *logrus.Logger, message ...string) *v1alpha1.NodeStatus { node := GetNodeByName(sensor, nodeName) if node.Phase != phase { log.WithFields( diff --git a/controllers/sensor/validate.go b/controllers/sensor/validate.go index fce5cadae4..5e4089bd70 100644 --- a/controllers/sensor/validate.go +++ b/controllers/sensor/validate.go @@ -18,6 +18,7 @@ package sensor import ( "fmt" + "strings" "time" "github.com/Knetic/govaluate" @@ -32,7 +33,7 @@ import ( // the error is ignored by the operation context as subsequent re-queues would produce the same error. // Exporting this function so that external APIs can use this to validate sensor resource. func ValidateSensor(s *v1alpha1.Sensor) error { - if err := validateSignals(s.Spec.Dependencies); err != nil { + if err := validateDependencies(s.Spec.Dependencies); err != nil { return err } err := validateTriggers(s.Spec.Triggers) @@ -88,36 +89,78 @@ func ValidateSensor(s *v1alpha1.Sensor) error { return nil } +// validateTriggers validates triggers func validateTriggers(triggers []v1alpha1.Trigger) error { if len(triggers) < 1 { return fmt.Errorf("no triggers found") } for _, trigger := range triggers { - if trigger.Template == nil { - return fmt.Errorf("trigger template can't be nil") - } - - if trigger.Template.Name == "" { - return fmt.Errorf("trigger must define a name") + if err := validateTriggerTemplate(trigger.Template); err != nil { + return err } - // each trigger must have a message or a resource - if trigger.Template.Source == nil { - return fmt.Errorf("trigger '%s' does not contain an absolute action", trigger.Template.Name) + if err := validateTriggerParameters(&trigger); err != nil { + return err } - if trigger.Template.GroupVersionKind == nil { - return fmt.Errorf("must provide group, version and kind for the resource") + } + return nil +} + +// validateTriggerTemplate validates trigger template +func validateTriggerTemplate(template *v1alpha1.TriggerTemplate) error { + if template == nil { + return fmt.Errorf("trigger template can't be nil") + } + if template.Name == "" { + return fmt.Errorf("trigger must define a name") + } + if template.Source == nil { + return fmt.Errorf("trigger '%s' does not contain an absolute action", template.Name) + } + if template.GroupVersionKind == nil { + return fmt.Errorf("must provide group, version and kind for the resource") + } + if template.When != nil && template.When.All != nil && template.When.Any != nil { + return fmt.Errorf("trigger condition can't have both any and all condition") + } + return nil +} + +// validateTriggerParameters validates resource and template parameters if any +func validateTriggerParameters(trigger *v1alpha1.Trigger) error { + if trigger.ResourceParameters != nil { + for i, parameter := range trigger.ResourceParameters { + if err := validateTriggerParameter(¶meter); err != nil { + return fmt.Errorf("resource parameter index: %d. err: %+v", i, err) + } } - if trigger.Template.When != nil && trigger.Template.When.All != nil && trigger.Template.When.Any != nil { - return fmt.Errorf("trigger condition can't have both any and all condition") + } + if trigger.TemplateParameters != nil { + for i, parameter := range trigger.TemplateParameters { + if err := validateTriggerParameter(¶meter); err != nil { + return fmt.Errorf("template parameter index: %d. err: %+v", i, err) + } } } return nil } -// perform a check to see that each event dependency defines one of and at most one of: -// (stream, artifact, calendar, resource, webhook) -func validateSignals(eventDependencies []v1alpha1.EventDependency) error { +// validateTriggerParameter validates a trigger parameter +func validateTriggerParameter(parameter *v1alpha1.TriggerParameter) error { + if parameter.Src == nil { + return fmt.Errorf("parameter source can't be empty") + } + if parameter.Src.Event == "" { + return fmt.Errorf("parameter source event can't be empty") + } + if parameter.Dest == "" { + return fmt.Errorf("parameter destination can't be empty") + } + return nil +} + +// perform a check to see that each event dependency is in correct format and has valid filters set if any +func validateDependencies(eventDependencies []v1alpha1.EventDependency) error { if len(eventDependencies) < 1 { return fmt.Errorf("no event dependencies found") } @@ -125,6 +168,16 @@ func validateSignals(eventDependencies []v1alpha1.EventDependency) error { if ed.Name == "" { return fmt.Errorf("event dependency must define a name") } + + parts := strings.Split(ed.Name, ":") + if len(parts) != 2 { + return fmt.Errorf("event dependency must have format gateway-name:event-source-name") + } + + if parts[0] == "" || parts[1] == "" { + return fmt.Errorf("both gateway name and event source name in dependency must be non-empty") + } + if err := validateEventFilter(ed.Filters); err != nil { return err } @@ -132,7 +185,9 @@ func validateSignals(eventDependencies []v1alpha1.EventDependency) error { return nil } +// validateEventFilter for a sensor func validateEventFilter(filter v1alpha1.EventDependencyFilter) error { + // validate time filter if filter.Time != nil { if err := validateEventTimeFilter(filter.Time); err != nil { return err @@ -141,6 +196,7 @@ func validateEventFilter(filter v1alpha1.EventDependencyFilter) error { return nil } +// validateEventTimeFilter validates time filter func validateEventTimeFilter(tFilter *v1alpha1.TimeFilter) error { currentT := time.Now().UTC() currentT = time.Date(currentT.Year(), currentT.Month(), currentT.Day(), 0, 0, 0, 0, time.UTC) diff --git a/docs/_config.yml b/docs/_config.yml deleted file mode 100644 index c4192631f2..0000000000 --- a/docs/_config.yml +++ /dev/null @@ -1 +0,0 @@ -theme: jekyll-theme-cayman \ No newline at end of file diff --git a/docs/assets/calendar.png b/docs/assets/calendar.png deleted file mode 100644 index e4fda13a6c7836174d5b2c7ef718ecade85401f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1334 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGojKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qucHK#pY978JN-p)Cj7aT6qYTUS-W8x2K0T=ce zuQNlROaAg}VCrP)Kd{1KvXEei^PzYhE04L3x~fMiTY0k5#V)+HeOI)#^LpW)rM2t& zPW@Zr?~)R~esg$EeEKBI!#$AH?w9OUi!$S zB*;ukJRn#qpl-J8BO4^y&$_o3Dql(U7yU4U-T(WK<7}}(QfW7~YWh^qOA;-;Y4m61 z4$Bul{cQQ}ERYB!5V!n#VhMzWN?n)t%}g_BRU-FI{-qW>4+r8dH1!=~LQf z8l09pd@1VOy-aK-Z)9$B zPfv^6v3G-m{NYPg=Yn|xX3N^VsQDlL9aOm$jD6k5qEcg$5K1~ ztj*1>89e8gefY%xe)Yp=Vm$Hf(<^1q|Jl3@BDbS3aJH<@k>2iGZxR&qVy>jIa~D2d zWM&=FAuSGa@SPni&i3tXUVLe8ELJ%_u}8;Tf$kSD*8^FFVw_a?{6AJ#?>yfMHqUL_ z5|i(hYeCLjG*MUcY;Bx2*l{V|Ud8jTcY*Aex;g0*3CeLe7i9k37fW`Y&jvfJH^(#c z-RCHfH(ivYgJ%8S69)3h#S_z}JhNLb3i71MCe@`RC;s*G=Uc)WhQUO@L_i#`N$nKAn}`?eFSw@0ZM RT>zGK44$rjF6*2UngCpPmHGex diff --git a/docs/assets/file.png b/docs/assets/file.png deleted file mode 100644 index 1a19ae80e9123a286369c85e54f41bea0c893b94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1706 zcmV;b237fqP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D20uweK~#8N?VD>) z990;{`^rRptH$elW8#OM#M<+8IxO>axu*%fdXkOC=Uq9~eZ zG&Z%hNfDb0<*F7e%PO~ph2#0poM#w@ncbP$nY|=D$v+*=o;m0F{pXxBXJ)sD4&orZ ziEvHF!;wI&J`$8~OTpM?Bp72Q(0n8yH#Ic$J|NO6PK4j+cuWe)H%t;LjkpOSHUC4v z-$KXj4Lw>Co2g01%BE)-TTgK&YKNCvwMo35S%Ts*4;Ggg8sPGio3}YMVedm!V7maYqmpdfffV!_+^ms1N9N-+i87~mN^)!ABCue|OYE0x>;&*2sEA)jN|>s3+%{DF6- zk{M7A@KDhWNVHtmIxSR5>52xD3}4Clxs|A{NWbu)2F>81M0h~!v`}?NbOvzPT%TKs z>WcIW4{Fd1zFdaAUPUvY9O0p&7@&tth6lAyy^@`|ZY63%q+fVYgJ$r!s)^Qqty8aL zXRcd`+7Rg%9@L;2e7OvJ68iJafJ%Tzf4&(|3GnF4M+3?q-d6*x;LUbyUMb(*V87Wu z8enzh&30^FDc9Y=4Blr0%6Hi7<(mPO01x?QfE9eA#hZ>B1yIIZ81FZI| zK6c{sKIORjswy0#44>inowzzZq@dg*P}~I>P>NxXD?ije%s#C8M9JaU=w%H!pK8Aq zYg0hZ@Tt%p4qbXBaI+HL3&81Uk_qM@D!`w%qOOFaP zdqF2VhR2r~klANBgpoFJ?Yf#UpT`*Xwcpsk@~Vo+FLn)ZIP3xL0-i=1-Q(-{qGk%^ zKy@Ru9>it^mi-_D{G9Vf_{BfQ*jaH;uN(f%6v~O}zUWihk^-^&d@+1ZpxFyDz$|eu zWQ1ShTUxsM@3(aAxz)K9+CW-|yuVINj>e6fpknrc8h3 zcguE1!2*A(qX!#r7eP72cZSakGNGXfBaJ=VUnwdp>s(lg?8J(!w`P=EYR!){sWRe zky6UZ<1p$1Ui{Frm&3p2>g^Ez3);su9g((B{4Zld#TJG#<}>#8$NAkszdqntc_G3V zJk&v5abB-LsodcA?w0|BHGvj02>S$VaB6YzbU^Qu#X=dzM2^X|UWBdeUpF>U;uq z9l!mlw1~VOe~J(Be(dd~H|1wU@j)Df?KpJkf0AEqvp3cEw*UYD07*qoM6N<$f^Ek? AU;qFB diff --git a/docs/assets/github-logo.png b/docs/assets/github-logo.png deleted file mode 100644 index 2fdd9b00d0e0fcab9a4f38eea3357ad5ef02e15a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1754 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 Mi9o>{&Ak%;0zy-wG5`Po diff --git a/docs/assets/k8s.png b/docs/assets/k8s.png deleted file mode 100644 index 18b15adfad4f013d12758a7ae4d0a6ca1ca7b0fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12690 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 diff --git a/docs/assets/netapp.png b/docs/assets/netapp.png deleted file mode 100644 index b1a55357602547198eb2eefccd50a0eda42b5e68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 695 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 diff --git a/docs/assets/slack.png b/docs/assets/slack.png deleted file mode 100644 index b6ecf59ca270b4760a8257752bd02321f3051f7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3829 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D4vI-cK~#8N?VNd3 zQ&%3xFYbuePHUHANxnQe&qpe$uBv@x@{}?;R&RAQV&eY>taVcW! zR!OiTiXd(zycb20Dy>R_3q^4!!J^a^Es*)W=Y@vkN8ZiSQkeDTE>Uwmnav1XI5_1nqEKz@BTse;#^;q@?(Xw4x{(_i!D_Xx-y z2VApmCsqvMXZ2a+ZTjoJcrze&A_%U-#M=VDQ!5-Ox|uKDh)`Of^i*TQF`yh>6-pJ| z+!s#+Qs>x9mIAJVS#)z>JPn-9MVMq~zyT0hun}gd2GH%Mh>aN;u8OKtAC$Rq*$p;m?PGM8c3&ISUHiKtp=_4f9G>Pa;-w?e~M|8#=z#^h69z=gb#^F=P5l(vzq+3yhpXH@_ zWo8N@Pho9|Id(%O7vlvTZyQk=G$Rt8(;WgE`a0E_s6<$4>nZj&10+Z{E zvl;&9KKr^4AGY=bkZ$}17tDfj8{G|=gxAh#BA5kE>+#GK%E=i_v@Mpc?aT{T_b|Mc z6l03{aSnm<|}8PkC=QCYXf|IeDIxp*3`GWDs|5 z!i}Uw(pH=&yQm|{GfjkHV>WQFLByk5GzT!bEOcN0ul+VcU8Hyl-7^^^FYP&8E)$Dr zD~>5DYD;p9N5SQ;ftq^*7jdixWLDVAWg#+Y*m1l~33R55;t3(E@Y)hPv8(U%N?jwXZjD-NAUcs_ZG9uq9d;=%RpcN!|NHl0ul`!|yAt&HMH8Oq!EBFQtp z0B6>GINQ%5op#D&85;^v!3+ei|93vtCW>$s3hP9&j6M~n_lVr)$lGw6Y+P1Ak`fEa z%HWV_LHHBFw6`*iR2jm-B0Gt zx=H4LVij318%85WtmDjtBv0Zo!ID53YPV~jV;K_8cAYT|X1s5aou%z*4`m*4$=N}C z9od?ElzjESy&$`)QMx^u+!+T6F7SB9`h%!o2D*Pcd#~7z&U71Ix4@16ZTa0~Sz=p; zvQ{4_E9V+O?qvtr7|CCGG&A+n9TUn>6(-mziwEDE^3AISPwTnqWdDiIv?nbzx}q** z^`cEsQp!=u&RFo-MNF(KJfA#aFDluQy4Yn=C)a%&SW=zUrdC+WsNYT|(_XZ&@TN}U z1W8z;)f;QbvW061FGJjpoeucN^A_8mP}ETWF73Kne={ zNv?4$bb1qT%T@x()N4?=ETnwp!OT=BLr0(t4X(D8K6J^T3v*ZZI##~L|CYUUTi^<~ zUB8C}&>qS(x{^2GMzsM(2iGwHBEl?j-mH_TU?~=U>hc`Go{;2s@?T!^qGi^qen*dQ z?!^4|MFF@9{!Du+v+$-~AiWUlFv_w;>rufhY%`oj+mzz|tT{OU$Ldwd0Xqy<~SlyH=t``aGMl>LD7baK=C_~rlcM=(m z`FXw#bnqzJd1nY^X#OWZIml&U!KdYDn~fOng7_?WozUD^9S%SOCYS}-HkLLcgXm0? zaS040EpY#4oW0lXnXR!7UU`yhnkGIAkO-W`Pr%tM4li8=wp&M=kwNsPoTegNVDs*c zs9YAlPBDmW=uAcM`Vr9|d4}#0bKp$oFu_v5c2(9Q(pb(OY;>jzO{BWQ{W9dngbXHe zYnNt;_Z|-dXYvP_U>54L$S~T>1CGvg4VBBvlKHGx!DVsTLRh|NSjxyt_3Qv_Bi-O2 zNPdI~1FnKqw3%j8+UvviW@UVjiXMM?lK#{0kozS7m&?NDUEd+H8>kW&=!Atj>>YL9 zdEZb0CRhsC&TLI2t!OiiF?Ux#Wl<*l-Ktah#oR{CWs531@ z#j>I^LK&KMp;5Z91T8E@3ro_%(zLzwrWDb=a651&&%gw;0NcJIv~fOA{aA%EUTsmR z^&q;oK{|$6p}tlb6z|2SWxC=X;`$CImzAXp)5M1^!owHgAq*}XXYYpYbWhxhHIoEm za;5k+!|%q0_q#0zp*d!S>K-P$SrqEK7DfDEx(i;2&NKrR>x_nn8F{8L#E>x*mCFLB zok91)?XZ5HtadA@xs=$p@Zg&r3%ICGxA~~fm*I@BME^;|l2O6Z)REk@ zZnPD*0;8e6w$fpUS^slV>*62B`S0Zi22|Qhx8?g6dKfUdOej>TbQioF;q2C%`itZA zbW=O}ug=4zzK+OcV{z7wjCfQswa|&b#5YYaHYR%GY>-jjJ2o4W%fk1eJ>4rqzgr1%H(c5%Trd*}v=ua06sm48 zT$~|X_LvO#Sv4OOP>Knbrt>+hO=(mzd$_Z6XM2}E#$*ep*+pAvOttc_f1nd24$k;G zT*7Y@hAB7Uf~7g#bIb{>&E|jue#A<~x2C%)qwpFHDp(3m3$x~RkDd=4=U<^vzXNC2 zHru5D7S8k>m4nG;p(wOBkF|**Ty5sSsUft-GE1IjEGpOut@NqZr&i3V`uyc_8{ka8 zfpwY%u?!6iIE@LG0!BmSSep(gRA(xKR5JSPn0>NWbp)w5?Iqje$7!rxzn*)2;Co|_ zkB)w!dQ4=fbwWh=QMA)8P#C7jzyz~!w&z=?ur@^$>JoF1`Xk{Ar9G8#cufW-U7(9* z@tyF5cTW6qQ1}%=x-GGhp>-#N->pCeFmk%r$Q_tm7Jdln*R%|QbYM<}BH=mOvlbFw zJHb|Zr%lU$4f!zc)X0~jF564DXKDXo%(WPUj)u-+f~7D-bt!AP(rvRd^%4Kfm3R8h zoL)Bk)tIxG=;oLhKHvvTtScNGpv=SsH%m;w`Qj-Z`0FXHernNQ^kMTbBY%2$Od%#% zir9#d+S1^-%a~YJ%6h-K3l(ikbSKM^@&1OZ%UT(&hp{$Yp&%?UOOP(C`xlPvSa4}h+d|=a z04CiY*_I)5kZKSJ-^@BenjRK?5ECp#Y-Gs2vf%eTDMN*&5i$Qb_i@|(zi#oniAi>b z?8=ap5I^YD7c9#GwxsuoJ&XxvVP(JJI;_oRQK*i?{>`=os(Xq1oJd+hIXRCBmO@zC z7CSDNK%uMK~hSI(WuwbG?tw_Qgfyk;@o6}JO2i!sU0fGa1CZvJ2+Otvtou5d0W4n{+v z0=D97h7TRIzxV79b6f9T*ZjkLPE$^I#qGcWh{q&12gtu-O($-bJ+B51z%)#%tEj`G zeiYVuMh=NO^z1*U?QWa%%|%o=2B(dnyW>`bZ`}f^xtMGW_+9yYp13?Hu7g>rF2$s> z0ORxuxQ{IV;-#^Z{4-aUp@JpRd_i}|?O1iB3&=It%eDo?*TL1|@mnRmp38yLqTot! z;ZdRLiZE8M2vQAg^5EM2?;AQvTkt5tr(!_zOu*tGKbst=&mlwUugWjNY*Tz#feIH_ zAg{vNzQz)mFrwKvt$Or*Lup=nKmzr>9UO!qKpaRPYt11&=#S(bL98W6Jr=HpwZJ|& zAi{dhl1im&l&SxC>9;Vt`h7#Ta2k2cOj~^1Ekm4E9y8MxAN>1<7|_ULX4>N8ei@R{ zcX+n+aN1%-uyeRndCW{7ityTa2f@zZG*<|pE{~b%LlNP7Lpe<@DjS2-w$N|7l5=$F zUEs!QK!yKC9mtp8%=Dp2(WS;(} diff --git a/docs/assets/sns.png b/docs/assets/sns.png deleted file mode 100644 index dc77a315ad8acc5f73e995e804a548194fe71ed9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4634 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 diff --git a/docs/assets/sqs.png b/docs/assets/sqs.png deleted file mode 100644 index 4312371d4f175b406f2a327ef14d297dc7e17473..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11978 zcmeHtbyyo)_byb?777$76fN#vybv6MOYkNTq)3q9dWsi{OY!3FR=mZfIE3O7qnFK;^yPx^1C&b>>I`#nGD8oX1^w?(4k7?2C>RcN(uToo z|IVVi6$}n@wt_j(004hxjfNQrHnX<>EoAxA3J4TYw0DMs?aiQyGU9Y-Kb+Rq<|0D8 z!UEi{1?6~N%klB>$O;R~Nb||c3G?#^@C)&yC4bw>z|36ip!V>;ZO#9&72^K4w!aI) z&H)`+2I^$(3N@E=g4xmh*>Mr;e~(4x-}?KPt@*#jA}ITBZMo23xPA}se=*#Di_kUn z`|zLQMW6gr{!n{#%{!rsdnZHd2m^!dwW5raw)^aEI`$_co#e{)#dF(NfxFn49dsq3 zxHy2 zYQgz-@%C+d#r~H1{Cu%jNmEl(;<-=8v9_kqdDD5zxwmBrIW;vY28KWOJA(Td7&Pdc z{0$!Zlni~B@}L_8-MY{%6cYpEe_i2!-Qs^3^Z!kkU(k=^|4U=?Plo?Pe*=nm0s;ag zUbO8OZ2;Y!-aFBiKH&UYixnu-TpM_V$?1qU}Ssr023oL3m*837j==A zuZ3IH+W(j8Clgu__DZd^eS*fA0ef9-821q#fGf z;P)|ORk?{Yh(emh02*{*Lzuy|#L9SB_kOGJ5=vM7j`>^cNUM_c8ztlo9s_IO)^jw- zH+Z30U4iPXzvF~vz3WzgC(SItLxY9xl>mfUhc>?WPlG}bPa#1hB5LHFrw_}Wdmbwq zyFVGL9G)sx<`~>U_{Ket^H0%$F5Wt0pc4_GiAKZ=B1sv^z@;t~@#_MUCODP|(1?>| z)Xn`zBIT;6r+kH$lu;-e7(g*pD##(t*Sp#%NPYh=Am&}4rC%FLmXFq>gYY|K&R$ zh?l?^s6_N9Y*`{e9?rMX?^=n&HZf*TlNri@btEqKzdNmhZR&ZKHOH!mWoCxtcZqR|0V$>VF=|graurtBK>YKqgdZSKV<#jiK)HyirEY_rg*alxXpGM2exm|eMzRbhp3*_{j?28oh* z5>47l%%<|goWrWLX=?J9aRoy7`I_lU;3eUYPRp@^!be}9Sletc{Vtj#mB7$P{P>sB zGI8DYb!BXcN^a$QG0A(U)ex`^>sqaYJrSv2EW2S#*9S8`0T&Ran$~&GQ0l5ta^Lhw zxp8y82vGE7RwFZztT?HVHe0&Ji-vY5V_P|o5m$I`jyET$ zigEKhlMO?2qa^)`OgHN$jft|983w2Mkh)i(JeI!sk)LN*-h(4!Q4LliCKC|RN5J$H zs>xcpq$NrzdnRiUor&;WpAMYzl-ukrKNnO14t!7dXD`Kk+wSaMMG>Om`*YM6wTYn= z-~4N;0W-;vonDEDH#2+ZUg}W{iAcxqh^Pqx{mi2K^SFV=b1zde9M1cw;mtW7CL>Rn zv?WnZL%FaSL6mzn``E;>uHjR?}t|b#2q0r7ti){)uv~ z4N5am>Rq7_32AqpmEZR}=f_<+I7Mm#d)K~fGaf!NyD69OMiQR8B=~yMbY^mB36HLQ z9@NkOg$>LcpNuUUE!?tk-IXGbw(or9)@a8!NQ+XMkcXq%*FE-hn{6DVBTHOuuH1lk zgaTR!pY&4d_SE-=%krLhun{SL!IX|UegT=+y|7u2t03y?r#9A?F?fEy!(AnF6b^%J zT9R$$)~<=bTaAfkmvs5FmK9>2ittYJb9dD21V>pI(@Z`TgzH5w_|Dg z0#Botag@>J#7C#oj}+^P*RBH_FQ<&Fr$gRl|1E}Pic>~a?WjNhl<4*4}2>5-m51;3ndZgI6sDWC9L%m^Xw zYCZLnoep?l*-HTi=Yh7 zs*=FDXw~z(?%Gv=Ov={zS+~|RcRA&6j1S`gv^)48q?X=DQ{5V7-Yg?Hj_P(Y6Ebh? zQ^l&=Ok?{Ui=G?F*@Hi}vwhuQKYCN7i#XCAa*)bIVI&ykp z`s{F4|Hs;S%A$t9v-l6=<^bgj6P_{OP9-5ul{mIz0hDIL;UD*?CdjW2*C}ndZ* z8>)XySJ3T{DGAGHV?jJsN9@U!@=R@5AdBp{!gT{NkB6hl%M$eM)>a$Z$F%!Gx}@=z z#!q?_?KfqBo10aO&8IE)qa##@jF|%oj7&*L>GJdiVxb_8B>EcuvN1dAIGc1}%tdkj zxvCR|?zD44hMCdGp<&#-Zuo&LO%f>vE=NWX*%4N=O6XUK-k#!3j@e-sFE#dreGjW7 zcL`_}g_}Grxwx~!6tZ>#l}ulJQ?%{eUOU1sNiVu?aLEMV(Skzz zUU7fsC1ZiGWo!0!m`8~%WGa2cud8-2iKDD8HGVSJ4%prqs7Z(`5sNrFv*b{=pQ<%% zA*=0PC6xhA$}ngQq}l`ZG?vyxY+!mM+jR*Ro3Il}5@+;x)g zCgsg9=M0VIGVyU8jp7$AzX^=hfqzL-SMMJ_FCK^m-%3v;q*%zjj>^Ysp9-|Sv;`nk*m5O>o zir@#G&AB;sCW-sgbn;ZAF<0!49UDKt$WR}(t~MYx76tIdc-G2(eZBW`)0wl=Q@aJh z0dt0V#u#&&X!Xw-74;%o6*>$j*uNh&2nCjU1(+1z-Y-w@KjUrnWgMC|*I$}N8s_-p zOZmZp5|U(9<`+Ss(_2JRKo?{2$!h?jRd%9ri;DokB{N-T<5Q5IWTAf!G2Zu^uj@|= zY?g1U=$Eu)`!PJ|NLxZR$r_|=+>G<_7f8hHx!N}Yfjz-LwzDT`gQy&CP!EN9&$$M+2K)+OaZ zOT1xvJ6GrVK5kLvu=H8q7uELl&!j*ldCJnaZHzK_tGUhK*!E-Pg*jic_Msy$!v$&i zzN^e9+wBk^r4uqvXNEKtcG3#jd5*Z(Qw>{f<9;Jd@b>g_;<%3<-QN33`HkDVXOGCq z$>Uxc=Zv@75VH`AuGQMTp6b~8KrK$cblJ_=XlCd3j^^uD&uML4{V_si%5&w4dfSlx zMEj$rANS0mg2Y~2$Ae7l*Bdl#t8pD&mxd*IOiYLGEvJV)PYlEs?$pJz=KMs==XUb1 zX03ay%3hV)`5E_R>wXZCRPOB(3Mstv52UMX2J)GIu9>oAvI?>Yum!@UD9G#n76SEE|qHf=p?pJ zLmOQY^yfHkd$z(Q@unN)E3JgXWzATUhns+5*u4_cAMsM02z>{azALwodCU7v>Ae7@ z!iv-`4_~fM-(GmT?lTdlxn^gbkXXFbpLYA-gSBz8^%$z^*z(6i70>tGi;wm09HjGj zHZyx8WZua!48!06h^3?|5XWWJssNvNW4@jOSpG0V3G@ZZy>=j)zjc-Tri}O0 z-3^sUd`Zy8yvSStZqehL8jgl$*Rs#O1SfM4Ch8~jHU{IngERv^>r7S7?Qys`jmFk% zAMuItGR}F*)z)S)d|dpJ$X}{TACrY3<0e=T9#vdE+o*fEU zx#GK>O~Jp)zYD~9YYhB2Uje(JV7nA@B8f0{AU8B7f9a_eW+Z7NXhSl#H{nfL?`IQ4 zjNqL0G;5b!wV0!0=OX|oGk1nuT_Rh+wo;$UNy!8Rd+sOdFCX zsMDGJPDkY@ak*h7yucR>D!+jHNA}XkhuI!O zMf_3+Z(8p1?!3<-@+#);zI zbK~06M{B1{K7Fk*dE>=3FzV%ZmfuxMt539O!}EI5##Hw1cyD}Klq%ALqS0CVDSA5V z(~dPg9LbOAK~$*>|Dls2Vv z^01qQO}P=_AF|nuiC0|~XO|^1wHzaK4@b;l*I?w5H)}X?1SkPrftN%G;{BvPh|q3+3~vB z{9Y(F^cO9ATAb%ZlsNSUxfART_slx6Gtu(NUPO|7U{=qV?Tg|F!2%>!i;G<+JgRkH2K7I)&cUX2Xk%=6@TdWF8%5C z+5Bf|?l{@6LFs`4^xRbgOcJaS>E{v%{UG83iNW%ki+a{8>BtLPwa*A}rlUF_^|_-) zoZ96JQoKZ1Y+MIWu(4@{WhqyOgh#UYt7J}@{QzwxE9r;Q#!$vRraB<$!)4=r$w}UW z%X)bAk-1F4A~0UWHtmiXiE1&BmRn*6bj+T)1sXM@PLOL@*HzGREYOmPL3u{kp&`XD zq|wzU=uHz4SJ5~x`55<=Jp(Q(wI7*To#1Pm0x~|E!P~TXFZz1z(`~~GUVH-vDTz~x zb}cY*PK|MV7TuHS$DWZAyUD?n7YbcIt(_JGsa3q+>)g#i92~z|uN;BY2$T;{lItue#g~%qk)z)TzwwsGvqg&Q$5YWPlQ?fI z7`KH?);ll-w<7SN4)0>lV2&G=g2*!`XN_Q?ug=}6Q*1c8#qMfBDBpC##76$kx*E-| z?Q-)`33w8uzfe3{a1;FfAFAg*Foxht?vY*<2(ytY)!JD{@;{?||qeqPj6PreibJ3k`!(*q5 zRMCH^F+9H9C-n-uaOx9zZgSm9wZpb>iLkCFv^a>4uFO5!dgpOQa6ew8J@U&ulQDMZ z75hzh&_ky@;gE(kr)5OwpnjiKvqkiC&+5^Y_Vwf3{KuEJ2TI9~=b8lT z=k{?{_>?M%2Nn4tPk7!aBJ=x0@=~hB@DC+TCYvYj~41wjVC^Q?R*s zt1(CCS^Rz7Mq9qRmr1=%f?l&TS8wkiGph`4&3hMK4YLk76;n`z&TLSPN9<`!+2Pmb zBhZ4ujZyL3MeL5P)qV1eWy7AeV^`yiV63@jK#PVGYbhI4 zzZaRAOWebFdCp9JVqS^u+4c$PS}K3?F7AD^D}vx_Fq6mlxuB21bC!9w#bsAS?4G*u z{wtu~2HnF3*v^7)GNTRI+t`|>xH47#8AMH%W@-O!uvmHW9@0whin&YtO&I1|oVB;f zqp2qxql*TTG$sYbpJTY27XYZGreR~uIsMHPNVy~UgV2^6I0tHQebLF+;t}~JT0zj( z6mkEx6@0|}!OBd_gH2_J5PrkE{Ae4?WJI3lqORW&Aye;Xs*X<1nmUA$r1MT5%(8$Y zcI z@5x-A@~!#qv4?of=Dibj+aWzBbCYr{H2a@jlAm}AfV>g3^%qQC_6guZ*{4JeGJf%k z%h$81rcEXd721fxw`v%CiS${;H#wKVJhSYC&%HWAFIy?KV6NFJY?>U(S+>fzD88d& z{@S+DjNWX(tdG$zSGD-j!`Yv? zna^P3XP*g4?IcVo(vRK(1)~luyD1t^0%CguxmJhvU6KtYt%{Y2x~e#R`mm2%JuH6M z?YncuFKd7-MHDHsx9V2$b5Qi?Ctz)yA$hSX-lBu})( z^W9Zj7g+MhBlDY7eq>Zqf8+NFc=%wT^U8rh>wE&I6FD3fnLp<=pSg!rTLrQ@dp+6V zaNTrukK8;H1oqk(a9j=vW2m=53X8^=EKPn*mR4PWln4M-n^2y$HL!Hiz4}HKTIORv zRlZv#GP#*W1Z+53(eQOIqgGW`oaLAC4y7et-1#fPu|f4N6pFX=wiJF^=?-Q~eRKPI z$=MusCTRMN?UlEtrz1nADKuI-O0I3Nu9Hdrxd`#q!hOINv(#rLsw4UJLjED77@@L<)>l7@F>cRn4epx$ z+NeNJwG)6+mwQH}~{C>UPEP*OOkg)WrmSk~ml_pWs6UFnAev z21&4xZ7R7xJm?i@m1}Vrc|dA?rTUyOoz_cD?FvS#`H5NfwmH8d*T*eXw7qPe*PkrE zNg+>>??_uo*5ka|owa6(K0+JBsvJi9oI3oa%YJ%;1C-ub^Q+smywSN_CRs$1B_ZHr z+#36%^9;x`q0NtazM*XZuhc|DeyEpJ0@o7}2kVaXg5-_F1`6gR^KitlbidxI^bep<4D=W+5tTcHju?x4K@>1H7lJkB*KoyvzSAo4=T(EeR3>b#Y zvL^1W=-zQij124OQEqDSzpfIryv<&T6sw;g`L)o&zIn#gb}&p*k+EuMuI5kX)PJ)h zaNO|8&$wh#sJ2Qm_xB*xM?q6^Uh z%_M%*cOPAx$J0M4{G5xE3#>Lwr++X4hxW$D5itWdJMWU^vOy;&@WK6zGG3}Vmb$RE z7aY!YQQaX)#D@f>cJ27*4oSP>9Yy#-b^z_UUqpzQUCjQ)5@Cw#2i^^$QF|wky_1R< z;&miUKW{ZupU*QNAWn3F)9ulaY4a z-;K{&n9Jo{EYqJ>D4y0EI-yF0UTikujZ;6hbxbbI1FoKmevycZsLfJO;_hAdJLqz& za|b3*RMGNDEXPh6-%O^@0p^R;Ng(c?S`GQ49PzYldhFA+D$hBLJ_m)o@Xcefu(DEU za|6mq? zsJaU5HQstF8w@=o<+8QtH{j6!vh|{$YyP1+739-fy#xEpiP;d%qQ)XcU3Np(>ylUK z9b`!0vKvRn%`NHV)Rri0FFGZc6va&*f3f>q@Il>_SBr8B=FXGh>eBALcJ{@ec|=GY zXsQ=op%A1rbY#YO-`h4j^QkbQc}L=PO8!Ww5LNug;*_=W;147K5&Ei6Vz-k^n*Gws z;m>!ISb?RWHtmh?8Qm30%HEyQGNSeU>ZS#g3{CtLVT#F#-Ou*%ul@L2H7Di-P&w{3 zMGwbTc-2x*cUAh0k||E|O$(o}YsmN2T@v4FP3Wwie#$5WB*%a~ys%24h@CE*w&qmP zm#ijuTM-{W_UCgLYHdX}9{_{W&P>}>boblE81S}V-E(UChPgG&6#a`KCS;TGT4Pdj=(< zOJPqWza3z}6N= zsFQ{a>+{E{_Zutd0IK)z-yd&v4u7Rt7V3GL*2~Hwqs?r4R*(L@B&&6$5MsA~oqCVg zSd#Df2Ta{qK1;L+rP1;$7XL>Qm0(R(V(H?#tFP}HJpDd0Cxa&Kl+;1`HS_8k0*$3| zJ58cF76HYBhqXB9zqIR$K)nysU3}@Jk3+w47W?@ITzc#}+kbUSEm)o}75d_`?PdD4 zk@nFWJdGK)wOj_QxWJ(Fjql0En!VdWq4fg}=;C2&GWTXT`AADgv3Fv!D$m`8k&nHwSIO?X54mR%B!8Me{hTY}7&vKPW#$cv@||I+*#aB0Ldw z{YedvjsC-1!0esg!!*Dsb6M5Bv^k`38U+TVFJW=PXCx%;1qJl7nxSZMnk|tdwK_Vk zzo^6}7?n*RIVul0R z|GL6GdCS#F0k%~`*K5cA^nz3CyCk!qpVA{9Pyz3bxn)q(LAX#^zKe=i9;{JCE5P2d zqcF9rkput2o~QwzCYU9kfVQCRR$^wVPA3*Hm&e(dN}#d75_`fTWEz9Ks=&Y4=R!Zb zag0-`T=Zw%EW@WMgkN5daUDaq5h^GAGtEgyBYds&p+Xs2o6e>b=6Tia zA(h!M{c{QBr@}K`l7mT2(Gy2`ei8+=7IDQcZ{+!wT5rp?9h9z*8S5je5+yQ~ukQwpf-_AtY{lcs3QmXi4~Wt> z<`RSQsqlpx;5?v;y{9&_BrEe9R!yURUIUXV9ymI3AE6N0Iep+q??ayuBf7<9Q<5q1 znPIyX-{bYr`>+nwnQ$Vhgk9 zcU>Gw!*1OrM16r%V9-wP$*-yBOc;Jx16T4lpotwm+Z`3Ar~OB6el;_h)}GHwV7g4}^^Za|q7n1y_g4mNUN%Ek=})Z>M8E zoJj>++Wr9QY>o>`hVS z56l6PTu(s59|~ZjaJCsHNFf$aF81on)sLy|)Q~q=m_L4IPb>KHmFY7?4Xso%hPbe+ zz|9^BuXT6=3zQs8gRvKLwkTpvsRMo8?0gjwVPveTc-HSLb!qhCOK1jk@EF(w;gKX2 zL8F5?63VMVzNOk%aH{JXU3py(yPPUlnIB10ref?SrIO-t4czfl8s@m*mt2d#Udqdh z36=zWS$sL?Y@QmLmEEnr|DIWhCn6$}K@`oX(WW(0?~wjwhQv(Yk^%Fj@9pqHY#hz2 zTvLf=wrPAhgRG}vKy|wg%97o>C$PZS6)CCX2 zq(!s%y417ZGuQvAgC;Ic+c-293`JR0nR4m3@Bb6p CQ+Bxk diff --git a/docs/assets/stream.png b/docs/assets/stream.png deleted file mode 100644 index ee65bf1d47e17f4b12d25bd5edc3103df450f823..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1482 zcmZ`(X*8P&6#Z;fCIm@}SZWE4u_dvm#?+o5NJMMtu_U%&DkLr1(4bTdN?XL%sjY_S zvF6#mS`x*co2qpF^09-@?z zV7UOGNH6OkS_=oF6jx^l0I1K=#t1tpI?k5?0I~z$AX1<&t0EL7nRtSu8ELpXvTGAN8PRFC#X4>1u|fR}|Ig(mm7|@{e6XcN~OYp{z){VolPKUF^+k5m!<+uaR;-IPPA?zY< z$ju|C+!2EYu>N@_SF32*x^!S1O401rb9&^GMRKB4g7M&*^HlcH8nRFX(0^I-E(rwB z;)HX5wY@VqlS<493Vo1;w|E;8h-E_BawwN3c~(-!9~qB&6lLEm2loDxEFHv?-pBlj zZGi6RDVo(zPS^y5sii}SZm{8PUcz21+r1a-f}2|4`zNGTSW#sjvOhZ_-O&@C z))Rss)I1_aXcr1WYGkC1d2Dr%dZ$uOO7iKtU~MZZT3z5+zKF2X?IaKu4Zsd1^d035 zRzK;*vO-e=VTFa8^sY-JFQw*4&hhfm*x6B;$^Nm<^D%JuINvdYduTNkb?fHI0r>@v zpYT$j*adZN;$6G)T{j^Qy>KE%m|^%0c`U6W|JXcaqab=+s{~!s?A3eN=1Z<$al51v z=_1PFyOdwMzxf%{AvHA`S);{K1i=E@jn&PQa!Iq={!T=nSjctC==!rb?T)8{Hp;FP zK0gL|s}5g9o@3Gjp{`ePMBQk`u@Oya(??W{S?ZI!$^viLt(Cc6Y8ze9GYGGbAkhpF zR`yoPqB~^sty=m3#PfS{SygsON*&XDs*+*j-jvf~(3g^?`f6MAD(}!=V#|Iy{KwbK zj;~j&@56?rTgqg+2FfmJ^(Fp?;7xXb9=9Xf^058atuFG34>{dl}8NJTQ^JQ8^bFFs6CK zdXus@Yqj$tqqKi|3D#*$#0`zNB-qVN@RTCeaTHAnOJ8<*9mvE1Tz-fXBY;j_CasaT zIwMgspI}jtFP;UXCyvncyIozOTe5n67}+hzFH6~EYv?w+(lB|wz2CGwJ*#or0+-9$ z_&AV97Gv2J>VaqUhECpw7N^!nkd2zsiZfPMoC|iI-I`rMnoi=wo8%{_PZc6RB^m zjq*-@WLi1B(v^(y&g*kJ%H$k{H}!|T;zON_FK`3qa|yZ+Ohs%mqZ2I{DH=BQ)QG3R z)T~>P?ZMfznQjOMZ!J7t$G{-G)*WUwSh70)e#aa^YtSgtS4aIv9 diff --git a/docs/assets/webhook.png b/docs/assets/webhook.png deleted file mode 100644 index e109cbcdcf7f3a12e70bc5505ea8c3bc5d0abe6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3446 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 -

Top

- -## pkg/apis/gateway/v1alpha1/generated.proto - - - - - -### Gateway -Gateway is the definition of a gateway resource -+genclient -+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -+k8s:openapi-gen=true - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| metadata | [k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta](#k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta) | optional | | -| status | [GatewayStatus](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.GatewayStatus) | optional | | -| spec | [GatewaySpec](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.GatewaySpec) | optional | | - - - - - - - - -### GatewayList -GatewayList is the list of Gateway resources -+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| metadata | [k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta](#k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta) | optional | | -| items | [Gateway](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.Gateway) | repeated | | - - - - - - - - -### GatewayNotificationWatcher -GatewayNotificationWatcher is the gateway interested in listening to notifications from this gateway - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| name | [string](#string) | optional | Name is the gateway name | -| port | [string](#string) | optional | Port is http server port on which gateway is running | -| endpoint | [string](#string) | optional | Endpoint is REST API endpoint to post event to. Events are sent using HTTP POST method to this endpoint. | - - - - - - - - -### GatewaySpec -GatewaySpec represents gateway specifications - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| Template | [k8s.io.api.core.v1.Pod](#k8s.io.api.core.v1.Pod) | optional | Template is the pod specification for the gateway Refer https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.11/#pod-v1-core | -| configmap | [string](#string) | optional | ConfigMap is name of the configmap for gateway. This configmap contains event sources. | -| type | [string](#string) | optional | Type is the type of gateway. Used as metadata. | -| eventVersion | [string](#string) | optional | Version is used for marking event version | -| serviceSpec | [k8s.io.api.core.v1.Service](#k8s.io.api.core.v1.Service) | optional | Service is the specifications of the service to expose the gateway Refer https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.11/#service-v1-core | -| watchers | [NotificationWatchers](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.NotificationWatchers) | optional | Watchers are components which are interested listening to notifications from this gateway These only need to be specified when gateway dispatch mechanism is through HTTP POST notifications. In future, support for NATS, KAFKA will be added as a means to dispatch notifications in which case specifying watchers would be unnecessary. | -| processorPort | [string](#string) | optional | Port on which the gateway event source processor is running on. | -| eventProtocol | [github.com.argoproj.argo_events.pkg.apis.common.EventProtocol](#github.com.argoproj.argo_events.pkg.apis.common.EventProtocol) | optional | EventProtocol is the underlying protocol used to send events from gateway to watchers(components interested in listening to event from this gateway) | - - - - - - - - -### GatewayStatus -GatewayStatus contains information about the status of a gateway. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| phase | [string](#string) | optional | Phase is the high-level summary of the gateway | -| startedAt | [k8s.io.apimachinery.pkg.apis.meta.v1.Time](#k8s.io.apimachinery.pkg.apis.meta.v1.Time) | optional | StartedAt is the time at which this gateway was initiated | -| message | [string](#string) | optional | Message is a human readable string indicating details about a gateway in its phase | -| nodes | [GatewayStatus.NodesEntry](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.GatewayStatus.NodesEntry) | repeated | Nodes is a mapping between a node ID and the node's status it records the states for the configurations of gateway. | - - - - - - - - -### GatewayStatus.NodesEntry - - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| key | [string](#string) | optional | | -| value | [NodeStatus](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.NodeStatus) | optional | | - - - - - - - - -### NodeStatus -NodeStatus describes the status for an individual node in the gateway configurations. -A single node can represent one configuration. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| id | [string](#string) | optional | ID is a unique identifier of a node within a sensor It is a hash of the node name | -| name | [string](#string) | optional | Name is a unique name in the node tree used to generate the node ID | -| displayName | [string](#string) | optional | DisplayName is the human readable representation of the node | -| phase | [string](#string) | optional | Phase of the node | -| startedAt | [k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime](#k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime) | optional | StartedAt is the time at which this node started +k8s:openapi-gen=false | -| message | [string](#string) | optional | Message store data or something to save for configuration | -| updateTime | [k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime](#k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime) | optional | UpdateTime is the time when node(gateway configuration) was updated | - - - - - - - - -### NotificationWatchers -NotificationWatchers are components which are interested listening to notifications from this gateway - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| gateways | [GatewayNotificationWatcher](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.GatewayNotificationWatcher) | repeated | Gateways is the list of gateways interested in listening to notifications from this gateway | -| sensors | [SensorNotificationWatcher](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.SensorNotificationWatcher) | repeated | Sensors is the list of sensors interested in listening to notifications from this gateway | - - - - - - - - -### SensorNotificationWatcher -SensorNotificationWatcher is the sensor interested in listening to notifications from this gateway - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| name | [string](#string) | optional | Name is name of the sensor | - - - - - - - - - - - - - - - -## Scalar Value Types - -| .proto Type | Notes | C++ Type | Java Type | Python Type | -| ----------- | ----- | -------- | --------- | ----------- | -| double | | double | double | float | -| float | | float | float | float | -| int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int | -| int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long | -| uint32 | Uses variable-length encoding. | uint32 | int | int/long | -| uint64 | Uses variable-length encoding. | uint64 | long | int/long | -| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | -| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long | -| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int | -| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long | -| sfixed32 | Always four bytes. | int32 | int | int | -| sfixed64 | Always eight bytes. | int64 | long | int/long | -| bool | | bool | boolean | boolean | -| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | -| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | - diff --git a/gateways/core/artifact/README.md b/docs/gateways/artifact.md similarity index 77% rename from gateways/core/artifact/README.md rename to docs/gateways/artifact.md index 2f8f11cb98..b295891a49 100644 --- a/gateways/core/artifact/README.md +++ b/docs/gateways/artifact.md @@ -1,10 +1,3 @@ -

- Minio S3 -

- -
- - # Minio S3 Artifact gateway listens to bucket notifications from Minio S3 server. If you are interested in AWS S3 then @@ -28,13 +21,13 @@ Refer AWS S3 Notitification - https://docs.aws.amazon.com/AmazonS3/latest/dev/no **Pre-requisite** - Create necessary bucket/s in Minio. -**1. Install [Gateway Configmap](../../../examples/gateways/artifact-gateway-configmap.yaml)** +**1. Install [Event Source](../../examples/event-sources/artifact.yaml)** -**2. Install [Gateway](../../../examples/gateways/artifact-http.yaml)** +**2. Install [Gateway](../../examples/gateways/artifact.yaml)** Make sure the gateway pod is created -**3. Install [Sensor](../../../examples/sensors/artifact.yaml)** +**3. Install [Sensor](../../examples/sensors/artifact.yaml)** **4. Trigger workflow** diff --git a/gateways/community/aws-sns/README.md b/docs/gateways/aws-sns.md similarity index 69% rename from gateways/community/aws-sns/README.md rename to docs/gateways/aws-sns.md index c840bcfc1b..f593166e89 100644 --- a/gateways/community/aws-sns/README.md +++ b/docs/gateways/aws-sns.md @@ -1,9 +1,3 @@ -

- AWS SNS -

- -
- # AWS SNS AWS SNS gateway listens to notifications from SNS. @@ -23,16 +17,16 @@ Depending upon the Kubernetes provider, you can create the Ingress or Route. ## Setup -**1. Install [Gateway](../../../examples/gateways/aws-sns.yaml)** +**1. Install [Gateway](../../examples/gateways/aws-sns.yaml)** -We are installing gateway before creating configmap. Because we need to have the gateway pod running and a service backed by the pod, so +We are installing gateway before creating event sources. Because we need to have the gateway pod running and a service backed by the pod, so that we can get the URL for the service. Make sure gateway pod and service is running -**2. Install [Gateway Configmap](../../../examples/gateways/aws-sns-gateway-configmap.yaml)** +**2. Install [Event Source](../../examples/event-sources/aws-sns.yaml)** -**3. Install [Sensor](../../../examples/sensors/aws-sns.yaml)** +**3. Install [Sensor](../../examples/sensors/aws-sns.yaml)** Make sure sensor pod is created. diff --git a/gateways/community/aws-sqs/README.md b/docs/gateways/aws-sqs.md similarity index 58% rename from gateways/community/aws-sqs/README.md rename to docs/gateways/aws-sqs.md index a03d5686ca..8a8c9057cf 100644 --- a/gateways/community/aws-sqs/README.md +++ b/docs/gateways/aws-sqs.md @@ -1,9 +1,3 @@ -

- AWS SQS -

- -
- # AWS SQS AWS SNS gateway consumes messages from SQS queue. @@ -15,13 +9,13 @@ Because SQS works on polling, you need to provide a `waitTimeSeconds`. ## Setup -**1. Install [Gateway](../../../examples/gateways/aws-sqs.yaml)** +**1. Install [Gateway](../../examples/gateways/aws-sqs.yaml)** Make sure gateway pod and service is running -**2. Install [Gateway Configmap](../../../examples/gateways/aws-sqs-gateway-configmap.yaml)** +**2. Install [Event Source](../../examples/event-sources/aws-sqs.yaml)** -**3. Install [Sensor](../../../examples/sensors/aws-sqs.yaml)** +**3. Install [Sensor](../../examples/sensors/aws-sqs.yaml)** Make sure sensor pod is created. diff --git a/gateways/core/calendar/README.md b/docs/gateways/calendar.md similarity index 82% rename from gateways/core/calendar/README.md rename to docs/gateways/calendar.md index ef5e2a7fad..94821896fd 100644 --- a/gateways/core/calendar/README.md +++ b/docs/gateways/calendar.md @@ -1,9 +1,3 @@ -

- Calendar -

- -
- # Calendar Calendar gateway can be used when you to schedule K8s resources on an interval @@ -31,13 +25,13 @@ This user defined data is `userPayload`. You can basically place any string here The [event payload](https://github.com/argoproj/argo-events/blob/a913dafbf000eb05401ef2c847b29152af82977f/gateways/core/calendar/config.go#L60-L64) contains `eventTime` and `userPayload` (optional) ## Setup -**1. Install [Gateway Configmap](../../../examples/gateways/calendar-gateway-configmap.yaml)** +**1. Install [Event Source](../../examples/event-sources/calendar.yaml)** -**2. Install [Gateway](../../../examples/gateways/calendar.yaml)** +**2. Install [Gateway](../../examples/gateways/calendar.yaml)** Make sure the gateway pod is created. -**3. Install [Sensor](../../../examples/sensors/calendar.yaml)** +**3. Install [Sensor](../../examples/sensors/calendar.yaml)** Make sure the sensor pod is created. diff --git a/gateways/core/file/README.md b/docs/gateways/file.md similarity index 76% rename from gateways/core/file/README.md rename to docs/gateways/file.md index 2712bf755d..6946ef108f 100644 --- a/gateways/core/file/README.md +++ b/docs/gateways/file.md @@ -1,9 +1,3 @@ -

- File -

- -
- # File File gateway watches changes to the file within specified directory. @@ -21,13 +15,13 @@ An entry in the gateway configmap corresponds to [this](https://github.com/argop ## Setup -**1. Install [Gateway Configmap](../../../examples/gateways/file-gateway-configmap.yaml)** +**1. Install [Event Source](../../examples/event-sources/file.yaml)** -**2. Install [Gateway](../../../examples/gateways/file.yaml)** +**2. Install [Gateway](../../examples/gateways/file.yaml)** Make sure the gateway pod is created. -**3. Install [Sensor](../../../examples/sensors/file.yaml)** +**3. Install [Sensor](../../examples/sensors/file.yaml)** Make sure the sensor pod is created. diff --git a/gateways/community/gcp-pubsub/README.md b/docs/gateways/gcp-pubsub.md similarity index 60% rename from gateways/community/gcp-pubsub/README.md rename to docs/gateways/gcp-pubsub.md index fe50cee32d..ae9f2c5d72 100644 --- a/gateways/community/gcp-pubsub/README.md +++ b/docs/gateways/gcp-pubsub.md @@ -1,9 +1,3 @@ -

- GCP PubSub -

- -
- # GCP PubSub GCP PubSub gateway listens to event streams on google cloud pub sub topics. @@ -15,13 +9,13 @@ An entry in the gateway configmap corresponds to [this](https://github.com/argop Make sure to mount credentials file for authentication in gateway pod and refer the path in `credentialsFile`. ## Setup -**1. Install [Gateway Configmap](../../../examples/gateways/gcp-pubsub-gateway-configmap.yaml)** +**1. Install [Event Source](../../examples/event-sources/gcp-pubsub.yaml)** -**2. Install [Gateway](../../../examples/gateways/gcp-pubsub.yaml)** +**2. Install [Gateway](../../examples/gateways/gcp-pubsub.yaml)** Make sure gateway pod and service is running -**3. Install [Sensor](../../../examples/sensors/gcp-pubsub.yaml)** +**3. Install [Sensor](../../examples/sensors/gcp-pubsub.yaml)** Make sure sensor pod is created. diff --git a/gateways/community/github/README.md b/docs/gateways/github.md similarity index 67% rename from gateways/community/github/README.md rename to docs/gateways/github.md index 9803cb9cd4..7c2a3c6d77 100644 --- a/gateways/community/github/README.md +++ b/docs/gateways/github.md @@ -1,9 +1,3 @@ -

- GitHub -

- -
- # Github The gateway listens to events from GitHub. @@ -25,16 +19,16 @@ Depending upon the Kubernetes provider, you can create the Ingress or Route. ## Setup -**1. Install [Gateway](../../../examples/gateways/github.yaml)** +**1. Install [Gateway](../../examples/gateways/github.yaml)** -We are installing gateway before creating configmap. Because we need to have the gateway pod running and a service backed by the pod, so +We are installing gateway before creating event sources. Because we need to have the gateway pod running and a service backed by the pod, so that we can get the URL for the service. Make sure gateway pod and service is running -**2. Install [Gateway Configmap](../../../examples/gateways/github-gateway-configmap.yaml)** +**2. Install [Event Source](../../examples/event-sources/github.yaml)** -**3. Install [Sensor](../../../examples/sensors/github.yaml)** +**3. Install [Sensor](../../examples/sensors/github.yaml)** Make sure sensor pod is created. diff --git a/gateways/community/gitlab/README.md b/docs/gateways/gitlab.md similarity index 63% rename from gateways/community/gitlab/README.md rename to docs/gateways/gitlab.md index f692e8d3c8..bf07b706c9 100644 --- a/gateways/community/gitlab/README.md +++ b/docs/gateways/gitlab.md @@ -1,10 +1,3 @@ -

- Gitlab -

- -
- - # Gitlab The gateway listens to events from Gitlab. @@ -22,16 +15,16 @@ Depending upon the Kubernetes provider, you can create the Ingress or Route. ## Setup -**1. Install [Gateway](../../../examples/gateways/gitlab.yaml)** +**1. Install [Gateway](../../examples/gateways/gitlab.yaml)** -We are installing gateway before creating configmap. Because we need to have the gateway pod running and a service backed by the pod, so +We are installing gateway before creating event sources. Because we need to have the gateway pod running and a service backed by the pod, so that we can get the URL for the service. Make sure gateway pod and service is running -**2. Install [Gateway Configmap](../../../examples/gateways/gitlab-gateway-configmap.yaml)** +**2. Install [Event Source](../../examples/event-sources/gitlab.yaml)** -**3. Install [Sensor](../../../examples/sensors/gitlab.yaml)** +**3. Install [Sensor](../../examples/sensors/gitlab.yaml)** Make sure sensor pod is created. diff --git a/gateways/core/resource/README.md b/docs/gateways/resource.md similarity index 74% rename from gateways/core/resource/README.md rename to docs/gateways/resource.md index 4ea2aee23b..4bd14169aa 100644 --- a/gateways/core/resource/README.md +++ b/docs/gateways/resource.md @@ -1,10 +1,3 @@ -

- K8s -

- -
- - # Resource Resource gateway listens to updates on **any** Kubernetes resource. @@ -27,13 +20,13 @@ The `namespace` event source defines configuration to listen to any updates to n Kubernetes Object the gateway is watching. ## Setup -**1. Install [Gateway Configmap](../../../examples/gateways/resource-gateway-configmap.yaml)** +**1. Install [Event Source](../../examples/event-sources/resource.yaml)** -**2. Install [Gateway](../../../examples/gateways/resource.yaml)** +**2. Install [Gateway](../../examples/gateways/resource.yaml)** Make sure the gateway pod is created. -**3. Install [Sensor](../../../examples/sensors/resource.yaml)** +**3. Install [Sensor](../../examples/sensors/resource.yaml)** Make sure the sensor pod is created. diff --git a/gateways/community/slack/README.md b/docs/gateways/slack.md similarity index 70% rename from gateways/community/slack/README.md rename to docs/gateways/slack.md index 24f5c7dbeb..b71fed76c1 100644 --- a/gateways/community/slack/README.md +++ b/docs/gateways/slack.md @@ -1,9 +1,3 @@ -

- Slack -

- -
- # Slack The gateway listens to events from Slack. @@ -24,13 +18,13 @@ Depending upon the Kubernetes provider, you can create the Ingress or Route. ## Setup -**1. Install [Gateway](../../../examples/gateways/slack.yaml)** +**1. Install [Gateway](../../examples/gateways/slack.yaml)** Make sure gateway pod and service is running -**2. Install [Gateway Configmap](../../../examples/gateways/slack-gateway-configmap.yaml)** +**2. Install [Event Source](../../examples/event-sources/slack.yaml)** -**3. Install [Sensor](../../../examples/sensors/slack.yaml)** +**3. Install [Sensor](../../examples/sensors/slack.yaml)** Make sure sensor pod is created. diff --git a/gateways/community/storagegrid/README.md b/docs/gateways/storage-grid.md similarity index 81% rename from gateways/community/storagegrid/README.md rename to docs/gateways/storage-grid.md index e67d1c20c5..0ac2c1baca 100644 --- a/gateways/community/storagegrid/README.md +++ b/docs/gateways/storage-grid.md @@ -1,9 +1,3 @@ -

- NetApp -

- -
- # StorageGrid The gateway listens to bucket notifications from storage grid. @@ -23,13 +17,13 @@ Depending upon the Kubernetes provider, you can create the Ingress or Route. ## Setup -**1. Install [Gateway](../../../examples/gateways/storage-grid.yaml)** +**1. Install [Gateway](../../examples/gateways/storage-grid.yaml)** Make sure gateway pod and service is running -**2. Install [Gateway Configmap](../../../examples/gateways/storage-grid-gateway-configmap.yaml)** +**2. Install [Event Source](../../examples/event-sources/storage-grid.yaml)** -**3. Install [Sensor](../../../examples/sensors/storage-grid.yaml)** +**3. Install [Sensor](../../examples/sensors/storage-grid.yaml)** Make sure sensor pod is created. diff --git a/gateways/core/stream/README.md b/docs/gateways/streams.md similarity index 57% rename from gateways/core/stream/README.md rename to docs/gateways/streams.md index d1d3005de2..b2230f5d7c 100644 --- a/gateways/core/stream/README.md +++ b/docs/gateways/streams.md @@ -1,10 +1,3 @@ -

- Stream -

- -
- - # Streams A Stream Gateway basically listens to messages on a message queue. @@ -20,18 +13,18 @@ An entry in the gateway configmap corresponds to [this](https://github.com/argop If you don't provide an explicit `Backoff`, then gateway will use a default backoff in case of connection failure. -The [event source](../../../examples/gateways/nats-gateway-configmap.yaml) contains information to subscribe to topic `foo`, it also contains an explicit backoff option +The [event source](../../examples/gateways/nats-gateway-configmap.yaml) contains information to subscribe to topic `foo`, it also contains an explicit backoff option in case of the connection failure. ### Setup -**1. Install [Gateway Configmap](../../../examples/gateways/nats-gateway-configmap.yaml)** +**1. Install [Event Source](../../examples/event-sources/nats.yaml)** -**2. Install [Gateway](../../../examples/gateways/nats.yaml)** +**2. Install [Gateway](../../examples/gateways/nats.yaml)** Make sure the gateway pod is created. -**3. Install [Sensor](../../../examples/sensors/nats.yaml)** +**3. Install [Sensor](../../examples/sensors/nats.yaml)** Make sure the sensor pod is created @@ -39,6 +32,3 @@ Make sure the sensor pod is created Publish message to subject `foo`. You might find this useful https://github.com/nats-io/go-nats/tree/master/examples/nats-pub - -## Setting up other stream gateways -You can follow examples [here](../../../examples/gateways) to setup other stream gateways. diff --git a/gateways/core/webhook/README.md b/docs/gateways/webhook.md similarity index 81% rename from gateways/core/webhook/README.md rename to docs/gateways/webhook.md index a797ab4b11..0b1409872a 100644 --- a/gateways/core/webhook/README.md +++ b/docs/gateways/webhook.md @@ -1,9 +1,3 @@ -

- Webhook -

- -
- # Webhook The webhook gateway basically runs one or more http servers in a pod. @@ -18,7 +12,7 @@ active endpoint and if you remove an endpoint entry, server will mark that endpo An entry in the gateway configmap corresponds to [this](https://github.com/argoproj/argo-events/blob/a913dafbf000eb05401ef2c847b29152af82977f/gateways/common/webhook.go#L32-L44) ### Example -The [configmap](../../../examples/gateways/secure-webhook-gateway-configmap.yaml) contains two event source configurations. +The [configmap](../../examples/gateways/secure-webhook-gateway-configmap.yaml) contains two event source configurations. The first entry `bar` defines the endpoint `/bar`, the HTTP method that will be allowed for the endpoint and the server port to register the endpoint on. @@ -41,13 +35,13 @@ If you don't to expose the gateway, just remove the `serviceSpec`. ## Setup -**1. Install [Gateway Configmap](../../../examples/gateways/webhook-gateway-configmap.yaml)** +**1. Install [Event Source](../../examples/event-sources/webhook.yaml)** -**2. Install [Gateway](../../../examples/gateways/webhook-http.yaml)** +**2. Install [Gateway](../../examples/gateways/webhook.yaml)** Make sure the gateway pod and service is created. -**3. Install [Sensor](../../../examples/sensors/webhook-http.yaml)** +**3. Install [Sensor](../../examples/sensors/webhook.yaml)** Make sure the sensor pod is created. @@ -74,5 +68,5 @@ If you want to have a secure server then you will need to mount the certifactes the configmap entry, set the values for `serverCertPath` and `serverKeyPath` accordingly. Example: -1. [Gateway](../../../examples/gateways/secure-webhook.yaml) -2. [Configmap](../../../examples/gateways/secure-webhook-gateway-configmap.yaml) +1. [Gateway](../../examples/gateways/secure-webhook.yaml) +2. [Configmap](../../examples/gateways/secure-webhook-gateway-configmap.yaml) diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000000..3b8ebb02f1 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,101 @@ +# Argo Events + +## Core Concepts +The framework is made up of two components: + + 1. **`Gateway`** which is implemented as a Kubernetes-native Custom Resource Definition processes events from event source. + + 2. **`Sensor`** which is implemented as a Kubernetes-native Custom Resource Definition defines a set of event dependencies and triggers K8s resources. + +## Install + +* ### Requirements + * Kubernetes cluster >v1.9 + * Installed the [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) command-line tool >v1.9.0 + +* ### Helm Chart + + Make sure you have helm client installed and Tiller server is running. To install helm, follow https://docs.helm.sh/using_helm/ + + 1. Add `argoproj` repository + + ```bash + helm repo add argo https://argoproj.github.io/argo-helm + ``` + + 2. Install `argo-events` chart + + ```bash + helm install argo/argo-events + ``` + +* ### Using kubectl + * Deploy Argo Events SA, Roles, ConfigMap, Sensor Controller and Gateway Controller + + ``` + kubectl create namespace argo-events + kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/argo-events-sa.yaml + kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/argo-events-cluster-roles.yaml + kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/sensor-crd.yaml + kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/gateway-crd.yaml + kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/sensor-controller-configmap.yaml + kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/sensor-controller-deployment.yaml + kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/gateway-controller-configmap.yaml + kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/hack/k8s/manifests/gateway-controller-deployment.yaml + ``` + +**Note**: If you have already deployed the argo workflow controller in another namespace +and the controller is namespace scoped, make sure to deploy a new controller in `argo-events` namespace. + +## Get Started +Lets deploy a webhook gateway and sensor, + + * First, we need to setup event sources for gateway to listen. The event sources for any gateway are managed using K8s configmap. + + ```bash + kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/examples/gateways/webhook-gateway-configmap.yaml + ``` + + * Create webhook gateway, + + ```bash + kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/examples/gateways/webhook-http.yaml + ``` + + After running above command, gateway controller will create corresponding gateway pod and a LoadBalancing service. + + * Create webhook sensor, + + ```bash + kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/examples/sensors/webhook-http.yaml + ``` + + Once sensor resource is created, sensor controller will create corresponding sensor pod and a ClusterIP service. + + * Once the gateway and sensor pods are running, trigger the webhook via a http POST request to `/foo` endpoint. + Note: the `WEBHOOK_SERVICE_URL` will differ based on the Kubernetes cluster. + ``` + export WEBHOOK_SERVICE_URL=$(minikube service -n argo-events --url ) + echo $WEBHOOK_SERVICE_URL + curl -d '{"message":"this is my first webhook"}' -H "Content-Type: application/json" -X POST $WEBHOOK_SERVICE_URL/foo + ``` + + Note: + * If you are facing an issue getting service url by running `minikube service -n argo-events --url `, you can use `kubectl port-forward` + * Open another terminal window and enter `kubectl port-forward -n argo-events 9003:` + * You can now use `localhost:9003` to query webhook gateway + + Verify that the Argo workflow was run when the trigger was executed. + ``` + argo list -n argo-events + ``` + + * More examples can be found at [examples](../examples) + +## Further Reading +1. [Gateway](gateway-guide.md) +2. [Sensor](sensor-guide.md) +3. [Trigger](trigger-guide.md) +4. [Communication between gateway and sensor](communication.md) +5. [Controllers](controllers-guide.md) +6. [Setup Gateways](gateways) diff --git a/docs/sensor-guide.md b/docs/sensor-guide.md index 7a85940da4..04798e5804 100644 --- a/docs/sensor-guide.md +++ b/docs/sensor-guide.md @@ -108,4 +108,3 @@ The `parameters` define list of ## Examples You can find sensor examples [here](https://github.com/argoproj/argo-events/tree/master/examples/sensors) - diff --git a/docs/sensor-protocol.md b/docs/sensor-protocol.md deleted file mode 100644 index 8ca4d083d8..0000000000 --- a/docs/sensor-protocol.md +++ /dev/null @@ -1,541 +0,0 @@ -# Protocol Documentation -
- -## Table of Contents - -- [pkg/apis/sensor/v1alpha1/generated.proto](#pkg/apis/sensor/v1alpha1/generated.proto) - - [ArtifactLocation](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.ArtifactLocation) - - [ConfigmapArtifact](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.ConfigmapArtifact) - - [DataFilter](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.DataFilter) - - [DependencyGroup](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.DependencyGroup) - - [EventDependency](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.EventDependency) - - [EventDependencyFilter](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.EventDependencyFilter) - - [FileArtifact](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.FileArtifact) - - [GitArtifact](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.GitArtifact) - - [GitCreds](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.GitCreds) - - [GitRemoteConfig](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.GitRemoteConfig) - - [GroupVersionKind](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.GroupVersionKind) - - [NodeStatus](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.NodeStatus) - - [ResourceObject](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.ResourceObject) - - [ResourceObject.LabelsEntry](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.ResourceObject.LabelsEntry) - - [ResourceParameter](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.ResourceParameter) - - [ResourceParameterSource](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.ResourceParameterSource) - - [RetryStrategy](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.RetryStrategy) - - [Sensor](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.Sensor) - - [SensorList](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.SensorList) - - [SensorSpec](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.SensorSpec) - - [SensorStatus](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.SensorStatus) - - [SensorStatus.NodesEntry](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.SensorStatus.NodesEntry) - - [TimeFilter](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.TimeFilter) - - [Trigger](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.Trigger) - - [TriggerCondition](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.TriggerCondition) - - [URLArtifact](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.URLArtifact) - - - - - -- [Scalar Value Types](#scalar-value-types) - - - - -

Top

- -## pkg/apis/sensor/v1alpha1/generated.proto - - - - - -### ArtifactLocation -ArtifactLocation describes the source location for an external artifact - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| s3 | [github.com.argoproj.argo_events.pkg.apis.common.S3Artifact](#github.com.argoproj.argo_events.pkg.apis.common.S3Artifact) | optional | | -| inline | [string](#string) | optional | | -| file | [FileArtifact](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.FileArtifact) | optional | | -| url | [URLArtifact](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.URLArtifact) | optional | | -| configmap | [ConfigmapArtifact](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.ConfigmapArtifact) | optional | | -| git | [GitArtifact](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.GitArtifact) | optional | | - - - - - - - - -### ConfigmapArtifact -ConfigmapArtifact contains information about artifact in k8 configmap - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| name | [string](#string) | optional | Name of the configmap | -| namespace | [string](#string) | optional | Namespace where configmap is deployed | -| key | [string](#string) | optional | Key within configmap data which contains trigger resource definition | - - - - - - - - -### DataFilter -DataFilter describes constraints and filters for event data -Regular Expressions are purposefully not a feature as they are overkill for our uses here -See Rob Pike's Post: https://commandcenter.blogspot.com/2011/08/regular-expressions-in-lexing-and.html - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| path | [string](#string) | optional | Path is the JSONPath of the event's (JSON decoded) data key Path is a series of keys separated by a dot. A key may contain wildcard characters '*' and '?'. To access an array value use the index as the key. The dot and wildcard characters can be escaped with '\\'. See https://github.com/tidwall/gjson#path-syntax for more information on how to use this. | -| type | [string](#string) | optional | Type contains the JSON type of the data | -| value | [string](#string) | repeated | Value is the allowed string values for this key Booleans are pased using strconv.ParseBool() Numbers are parsed using as float64 using strconv.ParseFloat() Strings are taken as is Nils this value is ignored | - - - - - - - - -### DependencyGroup -DependencyGroup is the group of dependencies - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| name | [string](#string) | optional | Name of the group | -| dependencies | [string](#string) | repeated | Dependencies of events | - - - - - - - - -### EventDependency -EventDependency describes a dependency - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| name | [string](#string) | optional | Name is a unique name of this dependency | -| deadline | [int64](#int64) | optional | Deadline is the duration in seconds after the StartedAt time of the sensor after which this event is terminated. Note: this functionality is not yet respected, but it's theoretical behavior is as follows: This trumps the recurrence patterns of calendar events and allows any event to have a strict defined life. After the deadline is reached and this event has not in a Resolved state, this event is marked as Failed and proper escalations should proceed. | -| filters | [EventDependencyFilter](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.EventDependencyFilter) | optional | Filters and rules governing tolerations of success and constraints on the context and data of an event | -| connected | [bool](#bool) | optional | Connected tells if subscription is already setup in case of nats protocol. | - - - - - - - - -### EventDependencyFilter -EventDependencyFilter defines filters and constraints for a event. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| name | [string](#string) | optional | Name is the name of event filter | -| time | [TimeFilter](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.TimeFilter) | optional | Time filter on the event with escalation | -| context | [github.com.argoproj.argo_events.pkg.apis.common.EventContext](#github.com.argoproj.argo_events.pkg.apis.common.EventContext) | optional | Context filter constraints with escalation | -| data | [DataFilter](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.DataFilter) | repeated | Data filter constraints with escalation | - - - - - - - - -### FileArtifact -FileArtifact contains information about an artifact in a filesystem - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| path | [string](#string) | optional | | - - - - - - - - -### GitArtifact -GitArtifact contains information about an artifact stored in git - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| url | [string](#string) | optional | Git URL | -| cloneDirectory | [string](#string) | optional | Directory to clone the repository. We clone complete directory because GitArtifact is not limited to any specific Git service providers. Hence we don't use any specific git provider client. | -| creds | [GitCreds](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.GitCreds) | optional | Creds contain reference to git username and password +optional | -| namespace | [string](#string) | optional | Namespace where creds are stored. +optional | -| sshKeyPath | [string](#string) | optional | SSHKeyPath is path to your ssh key path. Use this if you don't want to provide username and password. ssh key path must be mounted in sensor pod. +optional | -| filePath | [string](#string) | optional | Path to file that contains trigger resource definition | -| branch | [string](#string) | optional | Branch to use to pull trigger resource +optional | -| tag | [string](#string) | optional | Tag to use to pull trigger resource +optional | -| remote | [GitRemoteConfig](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.GitRemoteConfig) | optional | Git remote to manage set of tracked repositories. Defaults to "origin". Refer https://git-scm.com/docs/git-remote +optional | - - - - - - - - -### GitCreds -GitCreds contain reference to git username and password - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| username | [k8s.io.api.core.v1.SecretKeySelector](#k8s.io.api.core.v1.SecretKeySelector) | optional | | -| password | [k8s.io.api.core.v1.SecretKeySelector](#k8s.io.api.core.v1.SecretKeySelector) | optional | | - - - - - - - - -### GitRemoteConfig - - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| name | [string](#string) | optional | Name of the remote to fetch from. | -| urls | [string](#string) | repeated | URLs the URLs of a remote repository. It must be non-empty. Fetch will always use the first URL, while push will use all of them. | - - - - - - - - -### GroupVersionKind -GroupVersionKind unambiguously identifies a kind. It doesn't anonymously include GroupVersion -to avoid automatic coercion. It doesn't use a GroupVersion to avoid custom marshalling. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| group | [string](#string) | optional | | -| version | [string](#string) | optional | | -| kind | [string](#string) | optional | | - - - - - - - - -### NodeStatus -NodeStatus describes the status for an individual node in the sensor's FSM. -A single node can represent the status for event or a trigger. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| id | [string](#string) | optional | ID is a unique identifier of a node within a sensor It is a hash of the node name | -| name | [string](#string) | optional | Name is a unique name in the node tree used to generate the node ID | -| displayName | [string](#string) | optional | DisplayName is the human readable representation of the node | -| type | [string](#string) | optional | Type is the type of the node | -| phase | [string](#string) | optional | Phase of the node | -| startedAt | [k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime](#k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime) | optional | StartedAt is the time at which this node started | -| completedAt | [k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime](#k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime) | optional | CompletedAt is the time at which this node completed | -| message | [string](#string) | optional | store data or something to save for event notifications or trigger events | -| event | [github.com.argoproj.argo_events.pkg.apis.common.Event](#github.com.argoproj.argo_events.pkg.apis.common.Event) | optional | Event stores the last seen event for this node | - - - - - - - - -### ResourceObject -ResourceObject is the resource object to create on kubernetes - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| groupVersionKind | [GroupVersionKind](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.GroupVersionKind) | optional | The unambiguous kind of this object - used in order to retrieve the appropriate kubernetes api client for this resource | -| namespace | [string](#string) | optional | Namespace in which to create this object defaults to the service account namespace | -| source | [ArtifactLocation](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.ArtifactLocation) | optional | Source of the K8 resource file(s) | -| labels | [ResourceObject.LabelsEntry](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.ResourceObject.LabelsEntry) | repeated | Map of string keys and values that can be used to organize and categorize (scope and select) objects. This overrides any labels in the unstructured object with the same key. | -| parameters | [ResourceParameter](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.ResourceParameter) | repeated | Parameters is the list of resource parameters to pass in the object | - - - - - - - - -### ResourceObject.LabelsEntry - - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| key | [string](#string) | optional | | -| value | [string](#string) | optional | | - - - - - - - - -### ResourceParameter -ResourceParameter indicates a passed parameter to a service template - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| src | [ResourceParameterSource](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.ResourceParameterSource) | optional | Src contains a source reference to the value of the resource parameter from a event event | -| dest | [string](#string) | optional | Dest is the JSONPath of a resource key. A path is a series of keys separated by a dot. The colon character can be escaped with '.' The -1 key can be used to append a value to an existing array. See https://github.com/tidwall/sjson#path-syntax for more information about how this is used. | - - - - - - - - -### ResourceParameterSource -ResourceParameterSource defines the source for a resource parameter from a event event - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| event | [string](#string) | optional | Event is the name of the event for which to retrieve this event | -| path | [string](#string) | optional | Path is the JSONPath of the event's (JSON decoded) data key Path is a series of keys separated by a dot. A key may contain wildcard characters '*' and '?'. To access an array value use the index as the key. The dot and wildcard characters can be escaped with '\\'. See https://github.com/tidwall/gjson#path-syntax for more information on how to use this. | -| value | [string](#string) | optional | Value is the default literal value to use for this parameter source This is only used if the path is invalid. If the path is invalid and this is not defined, this param source will produce an error. | - - - - - - - - -### RetryStrategy -RetryStrategy represents a strategy for retrying operations -TODO: implement me - - - - - - - - -### Sensor -Sensor is the definition of a sensor resource -+genclient -+genclient:noStatus -+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -+k8s:openapi-gen=true - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| metadata | [k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta](#k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta) | optional | | -| spec | [SensorSpec](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.SensorSpec) | optional | | -| status | [SensorStatus](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.SensorStatus) | optional | | - - - - - - - - -### SensorList -SensorList is the list of Sensor resources -+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| metadata | [k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta](#k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta) | optional | | -| items | [Sensor](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.Sensor) | repeated | | - - - - - - - - -### SensorSpec -SensorSpec represents desired sensor state - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| dependencies | [EventDependency](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.EventDependency) | repeated | Dependencies is a list of the events that this sensor is dependent on. | -| triggers | [Trigger](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.Trigger) | repeated | Triggers is a list of the things that this sensor evokes. These are the outputs from this sensor. | -| deploySpec | [k8s.io.api.core.v1.PodSpec](#k8s.io.api.core.v1.PodSpec) | optional | Template contains sensor pod specification. For more information, read https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.11/#pod-v1-core | -| eventProtocol | [github.com.argoproj.argo_events.pkg.apis.common.EventProtocol](#github.com.argoproj.argo_events.pkg.apis.common.EventProtocol) | optional | EventProtocol is the protocol through which sensor receives events from gateway | -| circuit | [string](#string) | optional | Circuit is a boolean expression of dependency groups | -| dependencyGroups | [DependencyGroup](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.DependencyGroup) | repeated | DependencyGroups is a list of the groups of events. | - - - - - - - - -### SensorStatus -SensorStatus contains information about the status of a sensor. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| phase | [string](#string) | optional | Phase is the high-level summary of the sensor | -| startedAt | [k8s.io.apimachinery.pkg.apis.meta.v1.Time](#k8s.io.apimachinery.pkg.apis.meta.v1.Time) | optional | StartedAt is the time at which this sensor was initiated | -| completedAt | [k8s.io.apimachinery.pkg.apis.meta.v1.Time](#k8s.io.apimachinery.pkg.apis.meta.v1.Time) | optional | CompletedAt is the time at which this sensor was completed | -| completionCount | [int32](#int32) | optional | CompletionCount is the count of sensor's successful runs. | -| message | [string](#string) | optional | Message is a human readable string indicating details about a sensor in its phase | -| nodes | [SensorStatus.NodesEntry](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.SensorStatus.NodesEntry) | repeated | Nodes is a mapping between a node ID and the node's status it records the states for the FSM of this sensor. | - - - - - - - - -### SensorStatus.NodesEntry - - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| key | [string](#string) | optional | | -| value | [NodeStatus](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.NodeStatus) | optional | | - - - - - - - - -### TimeFilter -TimeFilter describes a window in time. -DataFilters out event events that occur outside the time limits. -In other words, only events that occur after Start and before Stop -will pass this filter. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| start | [string](#string) | optional | Start is the beginning of a time window. Before this time, events for this event are ignored and format is hh:mm:ss | -| stop | [string](#string) | optional | StopPattern is the end of a time window. After this time, events for this event are ignored and format is hh:mm:ss | - - - - - - - - -### Trigger -Trigger is an action taken, output produced, an event created, a message sent - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| name | [string](#string) | optional | Name is a unique name of the action to take | -| resource | [ResourceObject](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.ResourceObject) | optional | Resource describes the resource that will be created by this action | -| message | [string](#string) | optional | Message describes a message that will be sent on a queue | -| replyStrategy | [RetryStrategy](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.RetryStrategy) | optional | RetryStrategy is the strategy to retry a trigger if it fails | -| when | [TriggerCondition](#github.com.argoproj.argo_events.pkg.apis.sensor.v1alpha1.TriggerCondition) | optional | When is the condition to execute the trigger | - - - - - - - - -### TriggerCondition -TriggerCondition describes condition which must be satisfied in order to execute a trigger. -Depending upon condition type, status of dependency groups is used to evaluate the result. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| any | [string](#string) | repeated | Any acts as a OR operator between dependencies | -| all | [string](#string) | repeated | All acts as a AND operator between dependencies | - - - - - - - - -### URLArtifact -URLArtifact contains information about an artifact at an http endpoint. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| path | [string](#string) | optional | | -| verifyCert | [bool](#bool) | optional | | - - - - - - - - - - - - - - - -## Scalar Value Types - -| .proto Type | Notes | C++ Type | Java Type | Python Type | -| ----------- | ----- | -------- | --------- | ----------- | -| double | | double | double | float | -| float | | float | float | float | -| int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int | -| int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long | -| uint32 | Uses variable-length encoding. | uint32 | int | int/long | -| uint64 | Uses variable-length encoding. | uint64 | long | int/long | -| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | -| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long | -| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int | -| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long | -| sfixed32 | Always four bytes. | int32 | int | int | -| sfixed64 | Always eight bytes. | int64 | long | int/long | -| bool | | bool | boolean | boolean | -| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | -| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | - diff --git a/docs/setup.md b/docs/setup.md deleted file mode 100644 index 1b8565a345..0000000000 --- a/docs/setup.md +++ /dev/null @@ -1,15 +0,0 @@ -# Setup - -1. [Webhook](../gateways/core/webhook/README.md) -2. [Calendar](../gateways/core/calendar/README.md) -3. [Minio S3](../gateways/core/artifact/README.md) -4. [Resource](../gateways/core/resource/README.md) -5. [Stream](../gateways/core/stream/README.md) -6. [AWS SNS](../gateways/community/aws-sns/README.md) -7. [AWS SQS](../gateways/community/aws-sqs/README.md) -8. [GCP PubSub](../gateways/community/gcp-pubsub/README.md) -9. [Gitlab](../gateways/community/gitlab/README.md) -10. [Github](../gateways/community/github/README.md) -11. [HDFS](../gateways/community/hdfs) -12. [Slack](../gateways/community/slack/README.md) -13. [StorageGrid](../gateways/community/storagegrid/README.md) diff --git a/docs/trigger-guide.md b/docs/trigger-guide.md index 68ae4b5bad..8c26e5661d 100644 --- a/docs/trigger-guide.md +++ b/docs/trigger-guide.md @@ -25,7 +25,7 @@ The framework provides support to fetch trigger resources from different sources * ### File Artifacts are defined in a file that is mounted via a [PersistentVolume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) within the `sensor-controller` pod. - [Example](../examples/sensors/file-sensor.yaml) + [Example](../examples/sensors/trigger-source-file.yaml) * ### URL Artifacts are accessed from web via RESTful API. diff --git a/examples/event-sources/amqp.yaml b/examples/event-sources/amqp.yaml new file mode 100644 index 0000000000..d88ba6b5fd --- /dev/null +++ b/examples/event-sources/amqp.yaml @@ -0,0 +1,36 @@ +# This configmap contains the event sources configurations for AMQP gateway + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: amqp-event-source + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + # no retries if connection to amqp service is not successful + example-without-retry: |- + # url of the service + url: amqp://amqp.argo-events:5672 + # name of the exchange + exchangeName: "name of the exchange" + # type of the exchange + exchangeType: fanout + # routing key for the exchange + routingKey: "routing key" + + # retry after each backoff to set up a successful connection + example-with-retry: |- + url: amqp://amqp.argo-events:5672 + exchangeName: "name of the exchange" + exchangeType: fanout + routingKey: "routing key" + backoff: + # duration in nanoseconds. following value is 10 seconds + duration: 10000000000 + # how many backoffs + steps: 5 + # factor to increase on each step. + # setting factor > 1 makes backoff exponential. + factor: 2 diff --git a/examples/event-sources/artifact.yaml b/examples/event-sources/artifact.yaml new file mode 100644 index 0000000000..d6482bc1a9 --- /dev/null +++ b/examples/event-sources/artifact.yaml @@ -0,0 +1,61 @@ +# This configmap contains the event sources configurations for Artifact gateway + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: artifact-event-source + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + example-1: |- + # bucket information + bucket: + # name of the bucket + name: input + # s3 service endpoint + endpoint: minio-service.argo-events:9000 + # list of events to subscribe to + # Visit https://docs.minio.io/docs/minio-bucket-notification-guide.html + events: + - s3:ObjectCreated:Put + - s3:ObjectRemoved:Delete + # Filters to apply on the key + # Optional + # e.g. filter for key that starts with "hello-" and ends with ".txt" + filter: + prefix: "hello-" + suffix: ".txt" + # type of the connection + insecure: true + # accessKey refers to K8s secret that stores the access key + accessKey: + # Key within the K8s secret whose corresponding value (must be base64 encoded) is access key + key: accesskey + # Name of the K8s secret that contains the access key + name: artifacts-minio + # secretKey contains information about K8s secret that stores the secret key + secretKey: + # Key within the K8s secret whose corresponding value (must be base64 encoded) is secret key + key: secretkey + # Name of the K8s secret that contains the secret key + name: artifacts-minio + + example-2 : |- + bucket: + name: mybucket + endpoint: minio-service.argo-events:9000 + events: + - s3:ObjectCreated:Put + # no filter + filter: + prefix: "" + suffix: "" + insecure: true + accessKey: + key: accesskey + name: artifacts-minio + secretKey: + key: secretkey + name: artifacts-minio diff --git a/examples/event-sources/aws-sns.yaml b/examples/event-sources/aws-sns.yaml new file mode 100644 index 0000000000..6e8e20b5a6 --- /dev/null +++ b/examples/event-sources/aws-sns.yaml @@ -0,0 +1,58 @@ +# This configmap contains the event sources configurations for AWS SNS gateway + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: aws-sns-event-source + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + example: |- + # topic arn + topicArn: "topic-arn" + # hook contains configuration for the HTTP server running in the gateway. + # AWS will send events to following port and endpoint + hook: + # endpoint to listen events on + endpoint: "/" + # port to run HTTP server on + port: "12000" + # url the gateway will use to register at AWS. + # This url must be reachable from outside the cluster. + # The gateway pod is backed by the service defined in the gateway spec. So get the URL for that service AWS can reach to. + url: "http://myfakeurl.fake" + # accessKey contains information about K8s secret that stores the access key + accessKey: + # Key within the K8s secret whose corresponding value (must be base64 encoded) is access key + key: accesskey + # Name of the K8s secret that contains the access key + name: aws-secret + # secretKey contains information about K8s secret that stores the secret key + secretKey: + # Key within the K8s secret whose corresponding value (must be base64 encoded) is secret key + key: secretkey + # Name of the K8s secret that contains the secret key + name: aws-secret + # aws region + region: "us-east-1" + + example-with-secure-connection: |- + topicArn: "topic-arn" + hook: + endpoint: "/" + # gateway can run multiple HTTP servers, just define a unique port. + port: "13000" + url: "http://mysecondfakeurl.fake" + # path to file that is mounted in gateway pod which contains certs + serverCertPath: "some path in pod" + # path to file that is mounted in gateway pod which contains private key + serverKeyPath: "some path in pod" + accessKey: + name: aws-secret + key: access + secretKey: + name: aws-secret + key: secret + region: "us-east-1" diff --git a/examples/event-sources/aws-sqs.yaml b/examples/event-sources/aws-sqs.yaml new file mode 100644 index 0000000000..f8788cea65 --- /dev/null +++ b/examples/event-sources/aws-sqs.yaml @@ -0,0 +1,42 @@ +# This configmap contains the event sources configurations for AWS SQS gateway + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: aws-sqs-event-source + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + example-1: |- + # accessKey contains information about K8s secret that stores the access key + accessKey: + # Key within the K8s secret whose corresponding value (must be base64 encoded) is access key + key: accesskey + # Name of the K8s secret that contains the access key + name: aws-secret + # secretKey contains information about K8s secret that stores the secret key + secretKey: + # Key within the K8s secret whose corresponding value (must be base64 encoded) is secret key + key: secretkey + # Name of the K8s secret that contains the secret key + name: aws-secret + # aws region + region: "us-east-1" + # name of the queue. The gateway resolves the url of the queue from the queue name. + queue: "my-fake-queue-1" + # The duration (in seconds) for which the call waits for a message to arrive in the queue before returning. + # MUST BE > 0 AND <= 20 + waitTimeSeconds: 20 + + example-2: |- + accessKey: + key: accesskey + name: aws-secret + secretKey: + key: secretkey + name: aws-secret + region: "us-east-1" + queue: "my-fake-queue-2" + waitTimeSeconds: 20 diff --git a/examples/event-sources/calendar.yaml b/examples/event-sources/calendar.yaml new file mode 100644 index 0000000000..826b4be9aa --- /dev/null +++ b/examples/event-sources/calendar.yaml @@ -0,0 +1,44 @@ +# This configmap contains the event sources configurations for Calendar gateway + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: calendar-event-source + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + example-with-interval: |- + # creates an event every 10 seconds + interval: 10s + + example-with-schedule: |- + # schedules an event at 30 minutes past each hour + schedule: "30 * * * *" + + schedule-with-static-user-payload: |- + schedule: "30 * * * *" + # userPayload is a static string that will be send to the the sensor with each event payload + # whatever you put here is blindly delivered to sensor. + userPayload: "{\"hello\": \"world\"}" + + schedule-in-specific-timezone: |- + # creates an event every 20 seconds + interval: 20s + # userPayload is a static string that will be send to the the sensor with each event payload + # whatever you put here is blindly delivered to sensor. + userPayload: "{\"hello\": \"world\"}" + # timezone + # more info: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + timezone: "America/New_York" + + schedule-with-exclusion-dates: |- + schedule: "30 * * * *" + # more info https://icalendar.org/iCalendar-RFC-5545/3-8-5-3-recurrence-rule.html + # only exclusion dates are supported + # year, month and day are matched + recurrence: + - "EXDATE:20190102T150405Z" + - "EXDATE:20190602T160210Z" + timezone: "America/New_York" diff --git a/examples/event-sources/file.yaml b/examples/event-sources/file.yaml new file mode 100644 index 0000000000..57e5300280 --- /dev/null +++ b/examples/event-sources/file.yaml @@ -0,0 +1,25 @@ +# This configmap contains the event sources configurations for File gateway + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: file-configmap + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + example-with-path: |- + # directory to watch + directory: "/bin/" + # type of the event + # supported types are: CREATE, WRITE, REMOVE, RENAME, CHMOD + type: CREATE + # path to watch + path: x.txt + + example-with-path-regex: |- + directory: "/bin/" + type: CREATE + # the gateway will watch events for path that matches following regex + pathRegexp: "([a-z]+).txt" diff --git a/examples/event-sources/gcp-pubsub.yaml b/examples/event-sources/gcp-pubsub.yaml new file mode 100644 index 0000000000..360f76e5db --- /dev/null +++ b/examples/event-sources/gcp-pubsub.yaml @@ -0,0 +1,19 @@ +# This configmap contains the event sources configurations for GCP PubSub gateway + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: gcp-pubsub-configmap + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + example-1: |- + # id of your project + projectId: "my-fake-project-id" + # topic name + topic: "my-fake-topic" + # Refers to the credential file that is mounted in the gateway pod. + # ./validate.go is just a placeholder to make tests pass. Please place the path to actual credentials file :) + credentialsFile: "./validate.go" diff --git a/examples/event-sources/github.yaml b/examples/event-sources/github.yaml new file mode 100644 index 0000000000..cdc40f72ad --- /dev/null +++ b/examples/event-sources/github.yaml @@ -0,0 +1,77 @@ +# This configmap contains the event sources configurations for Github gateway +# More info: https://developer.github.com/v3/repos/hooks/#create-a-hook + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: github-event-source + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + example: |- + # id of the project + id: 123 + # owner of the repo + owner: "argoproj" + # repository name + repository: "argo-events" + # Github will send events to following port and endpoint + hook: + # endpoint to listen to events on + endpoint: "/push" + # port to run internal HTTP server on + port: "12000" + # url the gateway will use to register at Github. + # This url must be reachable from outside the cluster. + # The gateway pod is backed by the service defined in the gateway spec. So get the URL for that service Github can reach to. + url: "http://myfakeurl.fake" + # type of events to listen to. + # following listens to everything, hence * + # You can find more info on https://developer.github.com/v3/activity/events/types/ + events: + - "*" + # apiToken refers to K8s secret that stores the github api token + apiToken: + # Name of the K8s secret that contains the access token + name: github-access + # Key within the K8s secret whose corresponding value (must be base64 encoded) is access token + key: token + # webHookSecret refers to K8s secret that stores the github hook secret + webHookSecret: + # Name of the K8s secret that contains the hook secret + name: github-access + # Key within the K8s secret whose corresponding value (must be base64 encoded) is hook secret + key: secret + # type of the connection between gateway and Github + insecure: false + # Determines if notifications are sent when the webhook is triggered + active: true + # The media type used to serialize the payloads + contentType: "json" + + example-with-secure-connection: |- + id: 456 + owner: "argoproj" + repository: "argo" + hook: + endpoint: "/push" + port: "13000" + url: "http://myargofakeurl.fake" + # path to file that is mounted in gateway pod which contains certs + serverCertPath: "some path in pod" + # path to file that is mounted in gateway pod which contains private key + serverKeyPath: "some path in pod" + events: + - "push" + - "delete" + apiToken: + name: github-access + key: token + webHookSecret: + name: github-access + key: secret + insecure: true + active: true + contentType: "json" diff --git a/examples/event-sources/gitlab.yaml b/examples/event-sources/gitlab.yaml new file mode 100644 index 0000000000..0382e81bf5 --- /dev/null +++ b/examples/event-sources/gitlab.yaml @@ -0,0 +1,55 @@ +# This configmap contains the event sources configurations for Gitlab gateway +# More info: https://docs.gitlab.com/ce/api/projects.html#add-project-hook + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: gitlab-event-source + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + example: |- + # id of the project + projectId: "1" + # Github will send events to following port and endpoint + hook: + # endpoint to listen to events on + endpoint: "/push" + # port to run internal HTTP server on + port: "12000" + # url the gateway will use to register at Github. + # This url must be reachable from outside the cluster. + # The gateway pod is backed by the service defined in the gateway spec. So get the URL for that service Github can reach to. + url: "http://myfakeurl.fake" + # event to listen to + # Visit https://docs.gitlab.com/ee/user/project/integrations/webhooks.html#events + event: "PushEvents" + # accessToken refers to K8s secret that stores the gitlab api token + accessToken: + # Key within the K8s secret whose corresponding value (must be base64 encoded) is access token + key: accesskey + # Name of the K8s secret that contains the access token + name: gitlab-access + # Do SSL verification when triggering the hook + enableSSLVerification: false + # Gitlab Base url + gitlabBaseUrl: "YOUR_GITLAB_URL" + + example-secure: |- + projectId: "2" + hook: + endpoint: "/push" + port: "13000" + url: "http://mysecondfakeurl.fake" + # path to file that is mounted in gateway pod which contains certs + serverCertPath: "some path in pod" + # path to file that is mounted in gateway pod which contains private key + serverKeyPath: "some path in pod" + event: "PushEvents" + accessToken: + key: accesskey + name: gitlab-access + enableSSLVerification: true + gitlabBaseUrl: "YOUR_GITLAB_URL" diff --git a/examples/gateways/hdfs-configmap.yaml b/examples/event-sources/hdfs.yaml similarity index 78% rename from examples/gateways/hdfs-configmap.yaml rename to examples/event-sources/hdfs.yaml index afb81256a5..1e2a690d3f 100644 --- a/examples/gateways/hdfs-configmap.yaml +++ b/examples/event-sources/hdfs.yaml @@ -1,9 +1,15 @@ +# This configmap contains the event sources configurations for HDFS gateway + +--- apiVersion: v1 kind: ConfigMap metadata: name: hdfs-gateway-configmap + labels: + # do not remove + argo-events-event-source-version: v0.10 data: - tmpdir: |- + example-1: |- directory: "/tmp/" type: "CREATE" path: x.txt diff --git a/examples/event-sources/kafka.yaml b/examples/event-sources/kafka.yaml new file mode 100644 index 0000000000..055d0e7fd9 --- /dev/null +++ b/examples/event-sources/kafka.yaml @@ -0,0 +1,33 @@ +# This configmap contains the event sources configurations for Kafka gateway + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: kafka-event-source + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + # no retries if connection to kafka service is not successful + example-without-retry: |- + # url of the service + url: kafka.argo-events:9092 + # name of the topic + topic: "topic-1" + # partition number + partition: "0" + + # retry after each backoff to set up a successful connection + example-with-retry: |- + url: kafka.argo-events:9092 + topic: "topic-2" + partition: "1" + backoff: + # duration in nanoseconds. following value is 10 seconds + duration: 10000000000 + # how many backoffs + steps: 5 + # factor to increase on each step. + # setting factor > 1 makes backoff exponential. + factor: 2 diff --git a/examples/event-sources/mqtt.yaml b/examples/event-sources/mqtt.yaml new file mode 100644 index 0000000000..a7f1f4013f --- /dev/null +++ b/examples/event-sources/mqtt.yaml @@ -0,0 +1,34 @@ +# This configmap contains the event sources configurations for MQTT gateway + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: mqtt-event-source + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + # no retries if connection to mqtt service is not successful + example-without-retry: |- + # url of your mqtt service + url: tcp://mqtt.argo-events:1883 + # topic name + topic: foo + # client id + clientId: 1234 + + # retry after each backoff to set up a successful connection + example-with-retry: |- + url: tcp://mqtt.argo-events:1883 + topic: bar + # client id + clientId: 2345 + backoff: + # duration in nanoseconds. following value is 10 seconds + duration: 10000000000 + # how many backoffs + steps: 5 + # factor to increase on each step. + # setting factor > 1 makes backoff exponential. + factor: 2 diff --git a/examples/event-sources/nats.yaml b/examples/event-sources/nats.yaml new file mode 100644 index 0000000000..7d162a26cf --- /dev/null +++ b/examples/event-sources/nats.yaml @@ -0,0 +1,32 @@ +# This configmap contains the event sources configurations for NATS gateway + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: nats-event-source + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + # no retries if connection to nats service is not successful + example-without-retry: |- + # url of the nats service + url: nats://nats.argo-events:4222 + # subject name + subject: foo + + # retry after each backoff to set up a successful connection + example-with-retry: |- + # url of the nats service + url: nats://nats.argo-events:4222 + # subject name + subject: foo + backoff: + # duration in nanoseconds. following value is 10 seconds + duration: 10000000000 + # how many backoffs + steps: 5 + # factor to increase on each step. + # setting factor > 1 makes backoff exponential. + factor: 2 diff --git a/examples/event-sources/resource.yaml b/examples/event-sources/resource.yaml new file mode 100644 index 0000000000..c667c24f05 --- /dev/null +++ b/examples/event-sources/resource.yaml @@ -0,0 +1,84 @@ +# This configmap contains the event sources configurations for Resource gateway + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: resource-event-source + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + # watch workflows that are in successful state + example: |- + # namespace to listen events within + namespace: argo-events + # resource group + group: "argoproj.io" + # resource version + version: "v1alpha1" + # resource kind + kind: "Workflow" + # type of event + # possible values are ADDED, DELETED, MODIFIED, ERROR + # if not provided, listen to all events + # Optional + type: ADDED + # Filters to apply on watched object + # Optional + filter: + labels: + workflows.argoproj.io/phase: Succeeded + name: "my-workflow" + + # watch all namespace related events + example-with-all-types-and-no-filter: |- + namespace: argo-events + group: "k8s.io" + version: "v1" + kind: "Namespace" + + # create event if workflow with prefix "my-workflow" gets modified + example-with-prefix-filter: |- + namespace: argo-events + group: argoproj.io + version: v1alpha1 + kind: Workflow + type: MODIFIED + filter: + prefix: "my-workflow" + + # create event if pod with specified annotation gets deleted + example-with-annotations-filter: |- + namespace: argo-events + group: "k8s.io" + version: v1 + kind: Pod + type: DELETED + filter: + annotations: + gateways.argoproj.io/resource-spec-hash: "2978318157" + + # create event when a pod is created before 2019-03-27T010:52:32Z + example-with-created-by-filter: |- + namespace: argo-events + group: argoproj.io + version: v1alpha1 + kind: Workflow + type: ADDED + filter: + createdBy: "2019-04-06T12:52:11Z" + + example-with-multi-filters: |- + namespace: argo-events + group: "k8s.io" + version: v1 + kind: Pod + type: ADDED + filter: + createdBy: "2019-04-06T12:52:11Z" + annotations: + workflows.argoproj.io/node-name: hello-world-6j292 + labels: + workflows.argoproj.io/completed: "true" + prefix: "hello" diff --git a/examples/event-sources/slack.yaml b/examples/event-sources/slack.yaml new file mode 100644 index 0000000000..674ee9d38a --- /dev/null +++ b/examples/event-sources/slack.yaml @@ -0,0 +1,46 @@ +# This configmap contains the event sources configurations for Slack gateway + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: slack-event-source + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + example-1: |- + # hook contains configuration for the HTTP server running in the gateway. + # Slack will send events to following port and endpoint + hook: + # endpoint to listen events on + endpoint: "/" + # port to run HTTP server on + port: "12000" + # token contains information about K8s secret that stores the token + token: + # Name of the K8s secret that contains the token + name: slack-secret + # Key within the K8s secret whose corresponding value (must be base64 encoded) is token + key: tokenkey + + example-2: |- + hook: + endpoint: "/" + port: "13000" + token: + name: slack-secret-2 + key: tokenkey + + # with secure connection + example-3: |- + hook: + endpoint: "/" + port: "14000" + # path to file that is mounted in gateway pod which contains certs + serverCertPath: "some path in pod" + # path to file that is mounted in gateway pod which contains private key + serverKeyPath: "some path in pod" + token: + name: slack-secret-3 + key: tokenkey diff --git a/examples/event-sources/storage-grid.yaml b/examples/event-sources/storage-grid.yaml new file mode 100644 index 0000000000..aedf609408 --- /dev/null +++ b/examples/event-sources/storage-grid.yaml @@ -0,0 +1,38 @@ +# This configmap contains the event sources configurations for StorageGrid gateway + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: storage-grid-event-source + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + example: |- + # hook contains configuration for the HTTP server running in the gateway. + # StorageGrid will send events to following port and endpoint + hook: + # port to run HTTP server on + port: "8080" + # endpoint to listen events on + endpoint: "/" + # List of supported events can be derived from AWS S3 events https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html#supported-notification-event-types + # Remove S3 prefix from event type to make it a StorageGrid event. + events: + - "ObjectCreated:Put" + + example-secure: |- + hook: + # port to run HTTP server on + port: "8090" + # endpoint to listen events on + endpoint: "/" + # path to file that is mounted in gateway pod which contains certs + serverCertPath: "some path in pod" + # path to file that is mounted in gateway pod which contains private key + serverKeyPath: "some path in pod" + # for events object PUT, POST, COPY and object removal + events: + - "ObjectCreated:*" + - "ObjectRemoved:Delete" diff --git a/examples/event-sources/webhook.yaml b/examples/event-sources/webhook.yaml new file mode 100644 index 0000000000..81940cfc32 --- /dev/null +++ b/examples/event-sources/webhook.yaml @@ -0,0 +1,41 @@ +# This configmap contains the event sources configurations for Webhook gateway + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: webhook-event-source + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + # gateway can run multiple HTTP servers. Simply define a unique port to start a new HTTP server + + example: |- + # port to run HTTP server on + port: "12000" + # endpoint to listen to + endpoint: "/index" + # HTTP request method to allow. In this case, only POST requests are accepted + method: "POST" + + example-secure: |- + port: "13000" + endpoint: "/secure" + method: "POST" + # path to file that is mounted in gateway pod which contains certs + serverCertPath: "/bin/webhook-secure/crt" + # path to file that is mounted in gateway pod which contains private key + serverKeyPath: "/bin/webhook-secure/key" + + # example 3 and 4 shows how you can add multiple endpoints on same HTTP server + + example-3: |- + port: "14000" + endpoint: "/example3" + method: "PUT" + + example-4: |- + port: "14000" + endpoint: "/example4" + method: "POST" diff --git a/examples/gateways/amqp-gateway-configmap.yaml b/examples/gateways/amqp-gateway-configmap.yaml deleted file mode 100644 index 5063c293e3..0000000000 --- a/examples/gateways/amqp-gateway-configmap.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: amqp-gateway-configmap -data: - foo: |- - url: amqp://amqp.argo-events:5672 - exchangeName: fooExchangeName - exchangeType: fanout - routingKey: fooRoutingKey - bar: |- - url: amqp://amqp.argo-events:5672 - exchangeName: barExchangeName - exchangeType: fanout - routingKey: barRoutingKey diff --git a/examples/gateways/amqp.yaml b/examples/gateways/amqp.yaml index 112f9f6d83..72052eff6c 100644 --- a/examples/gateways/amqp.yaml +++ b/examples/gateways/amqp.yaml @@ -3,14 +3,26 @@ kind: Gateway metadata: name: amqp-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "amqp-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + # type of the gateway + type: "amqp" + # event source configmap name + eventSource: "amqp-event-source" + # port of the gateway server to send event source configuration to. + # you can configure it to any open port processorPort: "9330" + # protocol used to send event from gateway to sensor. HTTP in this case eventProtocol: type: "HTTP" + # port on which sensor is listening to events http: port: "9300" + # template is K8s PodSpec template: metadata: name: "amqp-gateway" @@ -27,9 +39,7 @@ spec: imagePullPolicy: "Always" command: ["/bin/amqp-gateway"] serviceAccountName: "argo-events-sa" - configMap: "amqp-gateway-configmap" - type: "amqp" - eventVersion: "1.0" + # sensors to send events to watchers: sensors: - name: "amqp-sensor" diff --git a/examples/gateways/artifact-gateway-configmap.yaml b/examples/gateways/artifact-gateway-configmap.yaml deleted file mode 100644 index fbdcc789b5..0000000000 --- a/examples/gateways/artifact-gateway-configmap.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: artifact-gateway-configmap -data: - input: |- - bucket: - name: input - endpoint: minio-service.argo-events:9000 - events: - - s3:ObjectCreated:Put - - s3:ObjectRemoved:Delete - filter: - prefix: "" - suffix: "" - insecure: true - accessKey: - key: accesskey - name: artifacts-minio - secretKey: - key: secretkey - name: artifacts-minio diff --git a/examples/gateways/artifact-nats-standard.yaml b/examples/gateways/artifact-nats-standard.yaml index 8cd9f76d42..d2c3813c55 100644 --- a/examples/gateways/artifact-nats-standard.yaml +++ b/examples/gateways/artifact-nats-standard.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: artifact-gateway-nats-standard labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "artifact-gateway-nats-standard" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "artifact" + eventSource: "artifact-event-source" processorPort: "9330" eventProtocol: type: "NATS" @@ -28,6 +33,3 @@ spec: imagePullPolicy: "Always" command: ["/bin/artifact-gateway"] serviceAccountName: "argo-events-sa" - configMap: "artifact-gateway-configmap" - eventVersion: "1.0" - type: "artifact" diff --git a/examples/gateways/artifact-nats-streaming.yaml b/examples/gateways/artifact-nats-streaming.yaml index 372ee9497e..4472965db6 100644 --- a/examples/gateways/artifact-nats-streaming.yaml +++ b/examples/gateways/artifact-nats-streaming.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: artifact-gateway-nats-streaming labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "artifact-gateway-nats-streaming" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "artifact" + eventSource: "artifact-event-source" processorPort: "9330" eventProtocol: type: "NATS" @@ -30,6 +35,3 @@ spec: imagePullPolicy: "Always" command: ["/bin/artifact-gateway"] serviceAccountName: "argo-events-sa" - configMap: "artifact-gateway-configmap" - eventVersion: "1.0" - type: "artifact" diff --git a/examples/gateways/artifact-http.yaml b/examples/gateways/artifact.yaml similarity index 76% rename from examples/gateways/artifact-http.yaml rename to examples/gateways/artifact.yaml index a016e01ba3..833b591ec5 100644 --- a/examples/gateways/artifact-http.yaml +++ b/examples/gateways/artifact.yaml @@ -3,8 +3,11 @@ kind: Gateway metadata: name: artifact-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "artifact-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: processorPort: "9330" eventProtocol: @@ -27,10 +30,9 @@ spec: imagePullPolicy: "Always" command: ["/bin/artifact-gateway"] serviceAccountName: "argo-events-sa" - configMap: "artifact-gateway-configmap" + eventSource: "artifact-event-source" eventVersion: "1.0" type: "artifact" watchers: sensors: - name: "artifact-sensor" - - name: "artifact-with-param-sensor" diff --git a/examples/gateways/aws-sns-gateway-configmap.yaml b/examples/gateways/aws-sns-gateway-configmap.yaml deleted file mode 100644 index a8a3a564d7..0000000000 --- a/examples/gateways/aws-sns-gateway-configmap.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# For more information, https://github.com/argoproj/argo-events/blob/e0242e7b00f7edc7e0cff314abd3a728ddf3c62b/gateways/community/aws-sns/config.go#L68 -apiVersion: v1 -kind: ConfigMap -metadata: - name: aws-sns-gateway-configmap -data: - notification_1: |- - topicArn: "topic-arn" - hook: - endpoint: "/" - port: "12000" - url: "placeholderurl" - accessKey: - name: aws-secret - key: access - secretKey: - name aws-secret - key: secret - region: "us-east-1" diff --git a/examples/gateways/aws-sns.yaml b/examples/gateways/aws-sns.yaml index 546aadca1f..0554dd099c 100644 --- a/examples/gateways/aws-sns.yaml +++ b/examples/gateways/aws-sns.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: aws-sns-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "aws-sns-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "aws-sns" + eventSource: "aws-sns-event-source" processorPort: "9330" eventProtocol: type: "HTTP" @@ -37,9 +42,6 @@ spec: - port: 12000 targetPort: 12000 type: LoadBalancer - configMap: "aws-sns-gateway-configmap" - eventVersion: "1.0" - type: "aws-sns" watchers: sensors: - name: "aws-sns-sensor" diff --git a/examples/gateways/aws-sqs-gateway-configmap.yaml b/examples/gateways/aws-sqs-gateway-configmap.yaml deleted file mode 100644 index f4f689e5c3..0000000000 --- a/examples/gateways/aws-sqs-gateway-configmap.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: aws-sqs-gateway-configmap -data: - notification_1: |- - accessKey: - name: aws-secret - key: access - secretKey: - name: aws-secret - key: secret - region: "us-east-1" - queue: "" - waitTimeSeconds: 20 diff --git a/examples/gateways/aws-sqs.yaml b/examples/gateways/aws-sqs.yaml index c3d4761abc..d7fea526c8 100644 --- a/examples/gateways/aws-sqs.yaml +++ b/examples/gateways/aws-sqs.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: aws-sqs-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "aws-sqs-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "aws-sqs" + eventSource: "aws-sqs-event-source" processorPort: "9330" eventProtocol: type: "HTTP" @@ -27,9 +32,6 @@ spec: imagePullPolicy: "Always" command: ["/bin/aws-sqs-gateway"] serviceAccountName: "argo-events-sa" - configMap: "aws-sqs-gateway-configmap" - eventVersion: "1.0" - type: "aws-sqs" watchers: sensors: - name: "aws-sqs-sensor" diff --git a/examples/gateways/calendar-gateway-configmap.yaml b/examples/gateways/calendar-gateway-configmap.yaml deleted file mode 100644 index b6d153c657..0000000000 --- a/examples/gateways/calendar-gateway-configmap.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: calendar-gateway-configmap -data: - interval: |- - interval: 10s - schedule: |- - schedule: "30 * * * *" diff --git a/examples/gateways/calendar.yaml b/examples/gateways/calendar.yaml index 9a9d04f93b..0aede586b1 100644 --- a/examples/gateways/calendar.yaml +++ b/examples/gateways/calendar.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: calendar-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "calendar-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "calendar" + eventSource: "calendar-event-source" processorPort: "9330" eventProtocol: type: "HTTP" @@ -27,9 +32,6 @@ spec: imagePullPolicy: "Always" command: ["/bin/calendar-gateway"] serviceAccountName: "argo-events-sa" - configMap: "calendar-gateway-configmap" - type: "calendar" - eventVersion: "1.0" watchers: sensors: - name: "calendar-sensor" diff --git a/examples/gateways/file-gateway-configmap.yaml b/examples/gateways/file-gateway-configmap.yaml deleted file mode 100644 index 26192bcbbd..0000000000 --- a/examples/gateways/file-gateway-configmap.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: file-gateway-configmap -data: - bindir: |- - directory: "/bin/" - type: CREATE - path: x.txt diff --git a/examples/gateways/file.yaml b/examples/gateways/file.yaml index c25d0b04a1..4388eab3a9 100644 --- a/examples/gateways/file.yaml +++ b/examples/gateways/file.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: file-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "file-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "file" + eventSource: "file-event-source" processorPort: "9330" eventProtocol: type: "HTTP" @@ -27,9 +32,6 @@ spec: imagePullPolicy: "Always" command: ["/bin/file-gateway"] serviceAccountName: "argo-events-sa" - configMap: "file-gateway-configmap" - eventVersion: "1.0" - type: "file" watchers: sensors: - name: "file-sensor" diff --git a/examples/gateways/gcp-pubsub-gateway-configmap.yaml b/examples/gateways/gcp-pubsub-gateway-configmap.yaml deleted file mode 100644 index 388e0d4440..0000000000 --- a/examples/gateways/gcp-pubsub-gateway-configmap.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: gcp-pubsub-gateway-configmap -data: - notification_1: |- - projectId: "your-project-id" - topic: "your-topic" - credentialsFile: "path to credential files" diff --git a/examples/gateways/gcp-pubsub.yaml b/examples/gateways/gcp-pubsub.yaml index 560aa9609d..53791536be 100644 --- a/examples/gateways/gcp-pubsub.yaml +++ b/examples/gateways/gcp-pubsub.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: gcp-pubsub-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "gcp-pubsub-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "gcp-pubsub" + eventSource: "gcp-pubsub-event-source" processorPort: "9330" eventProtocol: type: "HTTP" @@ -34,9 +39,6 @@ spec: secret: secretName: gcp-pubsub serviceAccountName: "argo-events-sa" - configMap: "gcp-pubsub-gateway-configmap" - eventVersion: "1.0" - type: "gcp-pubsub" watchers: sensors: - name: "gcp-pubsub-sensor" diff --git a/examples/gateways/github-gateway-configmap.yaml b/examples/gateways/github-gateway-configmap.yaml deleted file mode 100644 index 7930457657..0000000000 --- a/examples/gateways/github-gateway-configmap.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: github-gateway-configmap -data: - project_1: |- - id: 1234 - owner: "owner-example" - repository: "repo-example" - hook: - endpoint: "/push" - port: "12000" - url: "placeholderurl" - events: - - "*" - apiToken: - name: github-access - key: token - webHookSecret: - name: github-access - key: secret - insecure: false - active: true - contentType: "json" diff --git a/examples/gateways/github.yaml b/examples/gateways/github.yaml index 0cf169b9f1..1cc6f8a85b 100644 --- a/examples/gateways/github.yaml +++ b/examples/gateways/github.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: github-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "github-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "github" + eventSource: "github-event-source" processorPort: "9330" eventProtocol: type: "HTTP" @@ -37,9 +42,6 @@ spec: - port: 12000 targetPort: 12000 type: LoadBalancer - configMap: "github-gateway-configmap" - type: "github" - eventVersion: "1.0" watchers: sensors: - name: "github-sensor" diff --git a/examples/gateways/gitlab-gateway-configmap.yaml b/examples/gateways/gitlab-gateway-configmap.yaml deleted file mode 100644 index 9eee3acfad..0000000000 --- a/examples/gateways/gitlab-gateway-configmap.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: gitlab-gateway-configmap -data: - project_1: |- - id: 1234 - projectId: "1" - hook: - endpoint: "/push" - port: "12000" - url: "placeholderurl" - event: "PushEvents" - accessToken: - key: accesskey - name: gitlab-access - enableSSLVerification: false - gitlabBaseUrl: "YOUR_GITLAB_URL" diff --git a/examples/gateways/gitlab.yaml b/examples/gateways/gitlab.yaml index 68ed129afd..2dd59030ec 100644 --- a/examples/gateways/gitlab.yaml +++ b/examples/gateways/gitlab.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: gitlab-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "gitlab-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "gitlab" + eventSource: "gitlab-event-source" processorPort: "9330" eventProtocol: type: "HTTP" @@ -37,9 +42,6 @@ spec: - port: 12000 targetPort: 12000 type: LoadBalancer - configMap: "gitlab-gateway-configmap" - type: "gitlab" - eventVersion: "1.0" watchers: sensors: - name: "gitlab-sensor" diff --git a/examples/gateways/hdfs.yaml b/examples/gateways/hdfs.yaml index 215d695a6d..9b62f84424 100644 --- a/examples/gateways/hdfs.yaml +++ b/examples/gateways/hdfs.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: hdfs-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "hdfs-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "hdfs" + eventSource: "hdfs-event-source" processorPort: "9330" eventProtocol: type: "HTTP" @@ -27,9 +32,6 @@ spec: imagePullPolicy: "Always" command: ["/bin/hdfs-gateway"] serviceAccountName: "argo-events-sa" - configMap: "hdfs-gateway-configmap" - eventVersion: "1.0" - type: "hdfs" watchers: sensors: - name: "hdfs-sensor" diff --git a/examples/gateways/kafka-gateway-configmap.yaml b/examples/gateways/kafka-gateway-configmap.yaml deleted file mode 100644 index f712b7ea9e..0000000000 --- a/examples/gateways/kafka-gateway-configmap.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: kafka-gateway-configmap -data: - foo: |- - url: kafka.argo-events:9092 - topic: foo - partition: "0" - bar: |- - url: kafka.argo-events:9092 - topic: bar - partition: "1" diff --git a/examples/gateways/kafka.yaml b/examples/gateways/kafka.yaml index 47885659b4..e4b171dd6c 100644 --- a/examples/gateways/kafka.yaml +++ b/examples/gateways/kafka.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: kafka-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "kafka-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "kafka" + eventSource: "kafka-event-source" processorPort: "9330" eventProtocol: type: "HTTP" @@ -27,9 +32,6 @@ spec: imagePullPolicy: "Always" command: ["/bin/kafka-gateway"] serviceAccountName: "argo-events-sa" - configMap: "kafka-gateway-configmap" - type: "kafka" - eventVersion: "1.0" watchers: sensors: - name: "kafka-sensor" diff --git a/examples/gateways/mqtt-gateway-configmap.yaml b/examples/gateways/mqtt-gateway-configmap.yaml deleted file mode 100644 index b7eafd6825..0000000000 --- a/examples/gateways/mqtt-gateway-configmap.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: mqtt-gateway-configmap -data: - foo: |- - url: tcp://mqtt.argo-events:1883 - topic: foo - bar: |- - url: tcp://mqtt.argo-events:1883 - topic: bar diff --git a/examples/gateways/mqtt.yaml b/examples/gateways/mqtt.yaml index 98c6f6d633..58cd4beffa 100644 --- a/examples/gateways/mqtt.yaml +++ b/examples/gateways/mqtt.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: mqtt-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "mqtt-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "mqtt" + eventSource: "mqtt-event-source" processorPort: "9330" eventProtocol: type: "HTTP" @@ -27,9 +32,6 @@ spec: imagePullPolicy: "Always" command: ["/bin/mqtt-gateway"] serviceAccountName: "argo-events-sa" - configMap: "mqtt-gateway-configmap" - type: "mqtt" - eventVersion: "1.0" watchers: sensors: - name: "mqtt-sensor" diff --git a/examples/gateways/multi-watchers.yaml b/examples/gateways/multi-watchers.yaml index b9a83c3995..58d404bf69 100644 --- a/examples/gateways/multi-watchers.yaml +++ b/examples/gateways/multi-watchers.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: webhook-gateway-multi-watchers labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "webhook-gateway-multi-watchers" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "webhook" + eventSource: "webhook-event-source" processorPort: "9330" eventProtocol: type: "HTTP" @@ -27,9 +32,6 @@ spec: imagePullPolicy: "Always" command: ["/bin/webhook-gateway"] serviceAccountName: "argo-events-sa" - configMap: "webhook-gateway-configmap" - type: "webhook" - eventVersion: "1.0" service: metadata: name: webhook-gateway-svc diff --git a/examples/gateways/nats-gateway-configmap.yaml b/examples/gateways/nats-gateway-configmap.yaml deleted file mode 100644 index 931d16971b..0000000000 --- a/examples/gateways/nats-gateway-configmap.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: nats-gateway-configmap -data: - foo: |- - url: nats://nats.argo-events:4222 - subject: foo \ No newline at end of file diff --git a/examples/gateways/nats.yaml b/examples/gateways/nats.yaml index bfb7e404a0..2302a7f6e3 100644 --- a/examples/gateways/nats.yaml +++ b/examples/gateways/nats.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: nats-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "nats-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "nats" + eventSource: "nats-event-source" processorPort: "9330" eventProtocol: type: "HTTP" @@ -27,9 +32,6 @@ spec: imagePullPolicy: "Always" command: ["/bin/nats-gateway"] serviceAccountName: "argo-events-sa" - configMap: "nats-gateway-configmap" - type: "nats" - eventVersion: "1.0" watchers: sensors: - name: "nats-sensor" diff --git a/examples/gateways/resource-gateway-configmap.yaml b/examples/gateways/resource-gateway-configmap.yaml deleted file mode 100644 index 8a25688a69..0000000000 --- a/examples/gateways/resource-gateway-configmap.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# For more information, https://github.com/argoproj/argo-events/blob/e0242e7b00f7edc7e0cff314abd3a728ddf3c62b/gateways/core/resource/config.go#L34 -apiVersion: v1 -kind: ConfigMap -metadata: - name: resource-gateway-configmap -data: - workflow-success: |- - namespace: argo-events - group: "argoproj.io" - version: "v1alpha1" - kind: "Workflow" - type: ADDED - filter: - labels: - workflows.argoproj.io/phase: Succeeded - name: "my-workflow" - namespace: |- - namespace: argo-events - group: "k8s.io" - version: "v1" - kind: "Namespace" diff --git a/examples/gateways/resource.yaml b/examples/gateways/resource.yaml index c115638579..498f6f3f87 100644 --- a/examples/gateways/resource.yaml +++ b/examples/gateways/resource.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: resource-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "resource-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "resource" + eventSource: "resource-event-source" processorPort: "9330" eventProtocol: type: "HTTP" @@ -27,9 +32,6 @@ spec: imagePullPolicy: "Always" command: ["/bin/resource-gateway"] serviceAccountName: "argo-events-sa" - configMap: "resource-gateway-configmap" - type: "resource" - eventVersion: "1.0" watchers: sensors: - name: "resource-sensor" diff --git a/examples/gateways/secure-webhook-gateway-configmap.yaml b/examples/gateways/secure-webhook-gateway-configmap.yaml deleted file mode 100644 index 35b4d692f4..0000000000 --- a/examples/gateways/secure-webhook-gateway-configmap.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: webhook-gateway-configmap -data: - foo: |- - port: "12000" - endpoint: "/foo" - method: "POST" - # serverCertPath refers to file where certificate is stored - serverCertPath: "/etc/secret-volume/cert" - # serverKeyPath refers to file where private key is stored - serverKeyPath: "/etc/secret-volume/key" diff --git a/examples/gateways/secure-webhook.yaml b/examples/gateways/secure-webhook.yaml index 7c3095c2ce..94d9eb715a 100644 --- a/examples/gateways/secure-webhook.yaml +++ b/examples/gateways/secure-webhook.yaml @@ -3,17 +3,19 @@ kind: Gateway metadata: name: webhook-gateway-http labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "webhook-gateway-http" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: - configMap: "webhook-gateway-configmap" type: "webhook" + eventSource: "webhook-event-source" processorPort: "9330" eventProtocol: type: "HTTP" http: port: "9300" - eventVersion: "1.0" template: metadata: name: "webhook-gateway-http" diff --git a/examples/gateways/slack-gateway-configmap.yaml b/examples/gateways/slack-gateway-configmap.yaml deleted file mode 100644 index ccaeaf98e0..0000000000 --- a/examples/gateways/slack-gateway-configmap.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: slack-gateway-configmap -data: - notification_1: |- - hook: - endpoint: "/event" - port: "12000" - url: "URL_OF_SERVICE" - token: - name slack-secret - key: tokenkey diff --git a/examples/gateways/slack.yaml b/examples/gateways/slack.yaml index c1bbb7c229..e3c199fd82 100644 --- a/examples/gateways/slack.yaml +++ b/examples/gateways/slack.yaml @@ -3,9 +3,14 @@ kind: Gateway metadata: name: slack-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "slack-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: + type: "slack" + eventSource: "slack-event-source" processorPort: "9330" eventProtocol: type: "HTTP" @@ -37,9 +42,6 @@ spec: - port: 12000 targetPort: 12000 type: LoadBalancer - configMap: "slack-gateway-configmap" - type: "slack" - eventVersion: "1.0" watchers: sensors: - name: "slack-sensor" diff --git a/examples/gateways/storage-grid-gateway-configmap.yaml b/examples/gateways/storage-grid-gateway-configmap.yaml deleted file mode 100644 index b4deb63758..0000000000 --- a/examples/gateways/storage-grid-gateway-configmap.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: storage-grid-gateway-configmap -data: - foo: |- - hook: - port: "8080" - endpoint: "/" - events: - - "ObjectCreated:Put" diff --git a/examples/gateways/storage-grid.yaml b/examples/gateways/storage-grid.yaml index 56c845d867..a1ee944349 100644 --- a/examples/gateways/storage-grid.yaml +++ b/examples/gateways/storage-grid.yaml @@ -3,17 +3,19 @@ kind: Gateway metadata: name: storage-grid-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "storage-grid-gateway" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: - configMap: "storage-grid-gateway-configmap" - type: "storage_grid" + type: "storage-grid" + eventSource: "storage-grid-event-source" processorPort: "9330" eventProtocol: type: "HTTP" http: port: "9300" - eventVersion: "1.0" template: metadata: name: "storage-grid-gateway" diff --git a/examples/gateways/trello-gateway-configmap.yaml b/examples/gateways/trello-gateway-configmap.yaml deleted file mode 100644 index 4d5435d1b8..0000000000 --- a/examples/gateways/trello-gateway-configmap.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: trello-gateway-configmap -data: - notification_1: |- - hook: - endpoint: "/test" - port: "12000" - url: "placeholderurl" - apiKey: - name: trello-secret - key: apikey - token: - name trello-secret - key: tokenkey - description: "test webhook" diff --git a/examples/gateways/trello.yaml b/examples/gateways/trello.yaml deleted file mode 100644 index 0712158a69..0000000000 --- a/examples/gateways/trello.yaml +++ /dev/null @@ -1,45 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Gateway -metadata: - name: trello-gateway - labels: - gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "trello-gateway" -spec: - processorPort: "9330" - eventProtocol: - type: "HTTP" - http: - port: "9300" - template: - metadata: - name: "trello-gateway" - labels: - gateway-name: "trello-gateway" - spec: - containers: - - name: "gateway-client" - image: "argoproj/gateway-client" - imagePullPolicy: "Always" - command: ["/bin/gateway-client"] - - name: "trello-events" - image: "argoproj/trello-gateway" - imagePullPolicy: "Always" - command: ["/bin/trello-gateway"] - serviceAccountName: "argo-events-sa" - service: - metadata: - name: trello-gateway-svc - spec: - selector: - gateway-name: "trello-gateway" - ports: - - port: 12000 - targetPort: 12000 - type: LoadBalancer - configMap: "trello-gateway-configmap" - type: "trello" - eventVersion: "1.0" - watchers: - sensors: - - name: "trello-sensor" diff --git a/examples/gateways/webhook-gateway-configmap.yaml b/examples/gateways/webhook-gateway-configmap.yaml deleted file mode 100644 index e074b3011e..0000000000 --- a/examples/gateways/webhook-gateway-configmap.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: webhook-gateway-configmap -data: - index: |- - port: "12000" - endpoint: "/index" - method: "POST" - foo: |- - port: "12000" - endpoint: "/foo" - method: "POST" diff --git a/examples/gateways/webhook-nats-standard.yaml b/examples/gateways/webhook-nats-standard.yaml index 600032e04a..99d1e12c47 100644 --- a/examples/gateways/webhook-nats-standard.yaml +++ b/examples/gateways/webhook-nats-standard.yaml @@ -1,12 +1,15 @@ apiVersion: argoproj.io/v1alpha1 kind: Gateway metadata: - name: webhook-gateway-nats + name: webhook-gateway-with-standard-nats labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "webhook-gateway-nats" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: - configMap: "webhook-gateway-configmap" + eventSource: "webhook-event-source" type: "webhook" processorPort: "9330" eventProtocol: @@ -14,7 +17,6 @@ spec: nats: url: "nats://nats.argo-events:4222" type: "Standard" - eventVersion: "1.0" template: metadata: name: "webhook-gateway-nats" diff --git a/examples/gateways/webhook-nats-streaming.yaml b/examples/gateways/webhook-nats-streaming.yaml index c7c07930bc..c8dce83b24 100644 --- a/examples/gateways/webhook-nats-streaming.yaml +++ b/examples/gateways/webhook-nats-streaming.yaml @@ -1,13 +1,16 @@ apiVersion: argoproj.io/v1alpha1 kind: Gateway metadata: - name: webhook-gateway-nats-streaming + name: webhook-gateway-streaming-nats labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "webhook-gateway-nats-streaming" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: - configMap: "webhook-gateway-configmap" type: "webhook" + eventSource: "webhook-event-source" processorPort: "9330" eventProtocol: type: "NATS" @@ -16,7 +19,6 @@ spec: clusterId: "example-stan" clientId: "myclient" type: "Streaming" - eventVersion: "1.0" template: metadata: name: "webhook-gateway-nats-streaming" diff --git a/examples/gateways/webhook-http.yaml b/examples/gateways/webhook.yaml similarity index 54% rename from examples/gateways/webhook-http.yaml rename to examples/gateways/webhook.yaml index 99784e34ca..8f6bbc6e5c 100644 --- a/examples/gateways/webhook-http.yaml +++ b/examples/gateways/webhook.yaml @@ -1,24 +1,26 @@ apiVersion: argoproj.io/v1alpha1 kind: Gateway metadata: - name: webhook-gateway-http + name: webhook-gateway labels: + # gateway controller with instanceId "argo-events" will process this gateway gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "webhook-gateway-http" + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: - configMap: "webhook-gateway-configmap" type: "webhook" + eventSource: "webhook-event-source" processorPort: "9330" eventProtocol: type: "HTTP" http: port: "9300" - eventVersion: "1.0" template: metadata: name: "webhook-gateway-http" labels: - gateway-name: "webhook-gateway-http" + gateway-name: "webhook-gateway" spec: containers: - name: "gateway-client" @@ -29,17 +31,26 @@ spec: image: "argoproj/webhook-gateway" imagePullPolicy: "Always" command: ["/bin/webhook-gateway"] +# To make webhook secure, mount the secret that contains certificate and private key in the container +# and refer that mountPath in the event source. +# volumeMounts: +# - mountPath: "/bin/webhook-secure" +# name: secure +# volumes: +# - name: secure +# secret: +# secretName: webhook-secure serviceAccountName: "argo-events-sa" service: metadata: name: webhook-gateway-svc spec: selector: - gateway-name: "webhook-gateway-http" + gateway-name: "webhook-gateway" ports: - port: 12000 targetPort: 12000 type: LoadBalancer watchers: sensors: - - name: "webhook-sensor-http" + - name: "webhook-sensor" diff --git a/examples/sensors/amqp.yaml b/examples/sensors/amqp.yaml index 7b2d38fa9a..42389446e2 100644 --- a/examples/sensors/amqp.yaml +++ b/examples/sensors/amqp.yaml @@ -3,7 +3,11 @@ kind: Sensor metadata: name: amqp-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -17,7 +21,7 @@ spec: http: port: "9300" dependencies: - - name: "amqp-gateway:foo" + - name: "amqp-gateway:example-with-retry" triggers: - template: name: amqp-workflow-trigger @@ -48,5 +52,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "amqp-gateway:foo" + event: "amqp-gateway:example-with-retry" dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/artifact-with-param-nats-standard.yaml b/examples/sensors/artifact-with-param-nats-standard.yaml index 53e61de36b..77eb13ef77 100644 --- a/examples/sensors/artifact-with-param-nats-standard.yaml +++ b/examples/sensors/artifact-with-param-nats-standard.yaml @@ -3,7 +3,11 @@ kind: Sensor metadata: name: artifact-with-param-nats-standard-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -18,7 +22,7 @@ spec: type: "Standard" url: "nats://example-nats.argo-events:4222" dependencies: - - name: "artifact-gateway-nats-standard:input" + - name: "artifact-gateway-nats-standard:example-1" triggers: - template: name: argo-workflow @@ -42,6 +46,6 @@ spec: # The container args from the workflow are overridden by the s3 notification key resourceParameters: - src: - event: "artifact-gateway-nats-standard:input" + event: "artifact-gateway-nats-standard:example-1" path: s3.object.key dest: spec.templates.0.container.args.0 diff --git a/examples/sensors/artifact-with-param-nats-streaming.yaml b/examples/sensors/artifact-with-param-nats-streaming.yaml index 5b25264f1e..046fb8e8ae 100644 --- a/examples/sensors/artifact-with-param-nats-streaming.yaml +++ b/examples/sensors/artifact-with-param-nats-streaming.yaml @@ -3,7 +3,11 @@ kind: Sensor metadata: name: artifact-with-param-nats-streaming-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -20,7 +24,7 @@ spec: clusterId: "example-stan" clientId: "myclient1" dependencies: - - name: "artifact-gateway-nats-streaming:input" + - name: "artifact-gateway-nats-streaming:example-1" triggers: - template: name: argo-workflow @@ -44,6 +48,6 @@ spec: # The container args from the workflow are overridden by the s3 notification key resourceParameters: - src: - event: "artifact-gateway-nats-streaming:input" + event: "artifact-gateway-nats-streaming:example-1" path: s3.object.key dest: spec.templates.0.container.args.0 diff --git a/examples/sensors/artifact.yaml b/examples/sensors/artifact.yaml index 75ea51e1c6..3897679719 100644 --- a/examples/sensors/artifact.yaml +++ b/examples/sensors/artifact.yaml @@ -3,7 +3,11 @@ kind: Sensor metadata: name: artifact-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -17,10 +21,10 @@ spec: http: port: "9300" dependencies: - - name: "artifact-gateway:input" + - name: "artifact-gateway:example-1" triggers: - template: - name: artifact-workflow-trigger-2 + name: artifact-workflow-trigger group: argoproj.io version: v1alpha1 kind: Workflow @@ -43,6 +47,6 @@ spec: # The container args from the workflow are overridden by the s3 notification key resourceParameters: - src: - event: "artifact-gateway:input" + event: "artifact-gateway:example-1" path: s3.object.key dest: spec.templates.0.container.args.0 diff --git a/examples/sensors/aws-sns.yaml b/examples/sensors/aws-sns.yaml index 8c628b1ad2..49f9c7e1e6 100644 --- a/examples/sensors/aws-sns.yaml +++ b/examples/sensors/aws-sns.yaml @@ -3,7 +3,11 @@ kind: Sensor metadata: name: aws-sns-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -17,7 +21,7 @@ spec: http: port: "9300" dependencies: - - name: "aws-sns-gateway:notification_1" + - name: "aws-sns-gateway:example" triggers: - template: name: sns-workflow @@ -48,5 +52,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "aws-sns-gateway:notification_1" + event: "aws-sns-gateway:example" dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/aws-sqs.yaml b/examples/sensors/aws-sqs.yaml index 979802e5d8..b6f9537ec4 100644 --- a/examples/sensors/aws-sqs.yaml +++ b/examples/sensors/aws-sqs.yaml @@ -3,7 +3,11 @@ kind: Sensor metadata: name: aws-sqs-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -17,7 +21,7 @@ spec: http: port: "9300" dependencies: - - name: "aws-sqs-gateway:notification_1" + - name: "aws-sqs-gateway:example-1" triggers: - template: name: sqs-workflow @@ -48,5 +52,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "aws-sqs-gateway:notification_1" + event: "aws-sqs-gateway:example-1" dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/calendar.yaml b/examples/sensors/calendar.yaml index e07d80dc0b..db0ed47ab2 100644 --- a/examples/sensors/calendar.yaml +++ b/examples/sensors/calendar.yaml @@ -3,7 +3,11 @@ kind: Sensor metadata: name: calendar-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -13,7 +17,7 @@ spec: imagePullPolicy: Always serviceAccountName: argo-events-sa dependencies: - - name: "calendar-gateway:interval" + - name: "calendar-gateway:example-with-interval" eventProtocol: type: "HTTP" http: @@ -48,5 +52,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "calendar-gateway:interval" + event: "calendar-gateway:example-with-interval" dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/complete-trigger-parameterization.yaml b/examples/sensors/complete-trigger-parameterization.yaml index fbe1bc09b2..0e85b4206e 100644 --- a/examples/sensors/complete-trigger-parameterization.yaml +++ b/examples/sensors/complete-trigger-parameterization.yaml @@ -1,4 +1,4 @@ -# The event payload for this example = +# Consider an event payload, # # { # "name": "trigger-wf-1", @@ -18,7 +18,11 @@ kind: Sensor metadata: name: complete-trigger-parameterization-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -28,7 +32,7 @@ spec: imagePullPolicy: Always serviceAccountName: argo-events-sa dependencies: - - name: "webhook-gateway-http:foo" + - name: "webhook-gateway:example" eventProtocol: type: "HTTP" http: @@ -55,24 +59,24 @@ spec: # Apply parameter at template templateParameters: - src: - event: "webhook-gateway-http:foo" + event: "webhook-gateway:example" path: name dest: name - src: - event: "webhook-gateway-http:foo" + event: "webhook-gateway:example" path: namespace dest: namespace - src: - event: "webhook-gateway-http:foo" + event: "webhook-gateway:example" path: bucket dest: source.s3.bucket.name - src: - event: "webhook-gateway-http:foo" + event: "webhook-gateway:example" path: key dest: source.s3.bucket.key # Apply parameter for workflow resourceParameters: - src: - event: "webhook-gateway-http:foo" + event: "webhook-gateway:example" path: image dest: spec.templates.0.container.image diff --git a/examples/sensors/context-filter-webhook.yaml b/examples/sensors/context-filter-webhook.yaml index e2ee3c0a45..ed733be20d 100644 --- a/examples/sensors/context-filter-webhook.yaml +++ b/examples/sensors/context-filter-webhook.yaml @@ -3,7 +3,11 @@ kind: Sensor metadata: name: webhook-with-context-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -13,7 +17,7 @@ spec: imagePullPolicy: Always serviceAccountName: argo-events-sa dependencies: - - name: "webhook-gateway:foo" + - name: "webhook-gateway:example" filters: context: source: diff --git a/examples/sensors/data-filter-webhook.yaml b/examples/sensors/data-filter-webhook.yaml index 1b51340bee..2022187c0c 100644 --- a/examples/sensors/data-filter-webhook.yaml +++ b/examples/sensors/data-filter-webhook.yaml @@ -1,20 +1,23 @@ -# this is a non-repeatable sensor. To make it repeatable, set `repeat` as true in `spec` apiVersion: argoproj.io/v1alpha1 kind: Sensor metadata: name: webhook-with-data-filter-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: containers: - name: "sensor" - image: "argoproj/sensor:v0.7.1" + image: "argoproj/sensor" imagePullPolicy: Always serviceAccountName: argo-events-sa dependencies: - - name: "webhook-gateway-http:foo" + - name: "webhook-gateway:example" filters: name: "data-filter" data: @@ -57,5 +60,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "webhook-gateway-http:foo" + event: "webhook-gateway:example" dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/webhook-http-dependency-groups.yaml b/examples/sensors/dependencies-circuit-complex.yaml similarity index 94% rename from examples/sensors/webhook-http-dependency-groups.yaml rename to examples/sensors/dependencies-circuit-complex.yaml index f4dc9282bf..347dd27eb5 100644 --- a/examples/sensors/webhook-http-dependency-groups.yaml +++ b/examples/sensors/dependencies-circuit-complex.yaml @@ -1,12 +1,12 @@ -# The dependency grouping and selective workflow trigger execution is not supported in latest release -# This feature will be released in next release v0.8. -# You can try this example with sensor and sensor controller image v0.7.1 apiVersion: argoproj.io/v1alpha1 kind: Sensor metadata: name: webhook-sensor-http labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: diff --git a/examples/sensors/webhook-http-boolean.yaml b/examples/sensors/dependencies-circuit.yaml similarity index 90% rename from examples/sensors/webhook-http-boolean.yaml rename to examples/sensors/dependencies-circuit.yaml index 93a38af6e5..2a350105b1 100644 --- a/examples/sensors/webhook-http-boolean.yaml +++ b/examples/sensors/dependencies-circuit.yaml @@ -1,12 +1,12 @@ -# The dependency grouping and selective workflow trigger execution is not supported in latest release -# This feature will be released in next release v0.8. -# You can try this example with sensor and sensor controller image v0.7.1 apiVersion: argoproj.io/v1alpha1 kind: Sensor metadata: name: webhook-sensor-http-boolean-op labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: diff --git a/examples/sensors/file.yaml b/examples/sensors/file.yaml index b751042630..e4eb2cce54 100644 --- a/examples/sensors/file.yaml +++ b/examples/sensors/file.yaml @@ -3,17 +3,21 @@ kind: Sensor metadata: name: file-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: containers: - name: "sensor" - image: "argoproj/sensor:v0.6.3" + image: "argoproj/sensor" imagePullPolicy: Always serviceAccountName: argo-events-sa dependencies: - - name: "file-gateway:bindir" + - name: "file-gateway:example-with-path" eventProtocol: type: "HTTP" http: @@ -43,6 +47,6 @@ spec: name: whalesay resourceParameters: - src: - event: "file-gateway:bindir" + event: "file-gateway:example-with-path" path: name dest: spec.templates.0.container.args.1 diff --git a/examples/sensors/gcp-pubsub.yaml b/examples/sensors/gcp-pubsub.yaml index 33e5ef726b..5c9cbc1724 100644 --- a/examples/sensors/gcp-pubsub.yaml +++ b/examples/sensors/gcp-pubsub.yaml @@ -3,7 +3,11 @@ kind: Sensor metadata: name: gcp-pubsub-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -17,7 +21,7 @@ spec: http: port: "9300" dependencies: - - name: "gcp-pubsub-gateway:notification_1" + - name: "gcp-pubsub-gateway:example-1" triggers: - template: name: gcp-workflow @@ -48,5 +52,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "gcp-pubsub-gateway:notification_1" + event: "gcp-pubsub-gateway:example-1" dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/github.yaml b/examples/sensors/github.yaml index d9c4f6b352..e8c527525a 100644 --- a/examples/sensors/github.yaml +++ b/examples/sensors/github.yaml @@ -3,7 +3,11 @@ kind: Sensor metadata: name: github-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -13,7 +17,7 @@ spec: imagePullPolicy: Always serviceAccountName: argo-events-sa dependencies: - - name: "github-gateway:project_1" + - name: "github-gateway:example" eventProtocol: type: "HTTP" http: @@ -48,5 +52,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "github-gateway:project_1" + event: "github-gateway:example" dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/gitlab.yaml b/examples/sensors/gitlab.yaml index 9532c41349..e3bc79f6fd 100644 --- a/examples/sensors/gitlab.yaml +++ b/examples/sensors/gitlab.yaml @@ -3,7 +3,11 @@ kind: Sensor metadata: name: gitlab-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -17,7 +21,7 @@ spec: http: port: "9300" dependencies: - - name: "gitlab-gateway:project_1" + - name: "gitlab-gateway:example" triggers: - template: name: gitlab-workflow-trigger @@ -48,5 +52,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "gitlab-gateway:project_1" - dest: spec.arguments.parameters.0.value \ No newline at end of file + event: "gitlab-gateway:example" + dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/hdfs.yaml b/examples/sensors/hdfs.yaml index 3e970b03ac..1970d4819d 100644 --- a/examples/sensors/hdfs.yaml +++ b/examples/sensors/hdfs.yaml @@ -3,17 +3,21 @@ kind: Sensor metadata: name: hdfs-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: containers: - name: "sensor" - image: "argoproj/sensor:v0.6.3" + image: "argoproj/sensor" imagePullPolicy: Always serviceAccountName: argo-events-sa dependencies: - - name: "hdfs-gateway:tmpdir" + - name: "hdfs-gateway:example-1" eventProtocol: type: "HTTP" http: @@ -42,6 +46,6 @@ spec: image: "docker/whalesay:latest" resourceParameters: - src: - event: "hdfs-gateway:tmpdir" + event: "hdfs-gateway:example-1" path: name dest: spec.templates.0.container.args.1 diff --git a/examples/sensors/kafka.yaml b/examples/sensors/kafka.yaml index e3422c87fa..8bb606d4c8 100644 --- a/examples/sensors/kafka.yaml +++ b/examples/sensors/kafka.yaml @@ -3,7 +3,11 @@ kind: Sensor metadata: name: kafka-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -17,7 +21,7 @@ spec: http: port: "9300" dependencies: - - name: "kafka-gateway:foo" + - name: "kafka-gateway:example-with-retry" triggers: - template: name: kafka-workflow-trigger @@ -48,5 +52,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "kafka-gateway:foo" + event: "kafka-gateway:example-with-retry" dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/mqtt-sensor.yaml b/examples/sensors/mqtt-sensor.yaml index dc3c0c765e..9bda17c81c 100644 --- a/examples/sensors/mqtt-sensor.yaml +++ b/examples/sensors/mqtt-sensor.yaml @@ -3,7 +3,11 @@ kind: Sensor metadata: name: mqtt-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -17,7 +21,7 @@ spec: http: port: "9300" dependencies: - - name: "mqtt-gateway:foo" + - name: "mqtt-gateway:example-with-retry" triggers: - template: name: mqtt-workflow-trigger @@ -48,5 +52,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "mqtt-gateway:foo" + event: "mqtt-gateway:example-with-retry" dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/multi-signal-sensor.yaml b/examples/sensors/multi-signal-sensor.yaml index e9ce2cb08d..976c87c53e 100644 --- a/examples/sensors/multi-signal-sensor.yaml +++ b/examples/sensors/multi-signal-sensor.yaml @@ -3,7 +3,11 @@ kind: Sensor metadata: name: multi-signal-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -18,8 +22,8 @@ spec: port: "9300" # wait for both "webhook-gateway-http:foo" and "calendar-gateway:interval" to happen dependencies: - - name: "webhook-gateway-http:foo" - - name: "calendar-gateway:interval" + - name: "webhook-gateway-http:example" + - name: "calendar-gateway:example-with-interval" triggers: - template: name: multi-signal-workflow-trigger @@ -36,8 +40,11 @@ spec: entrypoint: whalesay arguments: parameters: - - name: message - # this is the value that should be overridden + - name: message1 + # this is the value that should be overridden by event payload from webhook-gateway-http:foo + value: hello world + - name: message2 + # this is the value that should be overridden by event payload from calendar-gateway:interval value: hello world templates: - name: whalesay @@ -47,8 +54,13 @@ spec: container: image: docker/whalesay:latest command: [cowsay] - args: ["{{inputs.parameters.message}}"] + args: + - "{{inputs.parameters.message1}}" + - "{{inputs.parameters.message2}}" resourceParameters: - src: - event: "webhook-gateway-http:foo" - dest: spec.arguments.parameters.0.value \ No newline at end of file + event: "webhook-gateway:example" + dest: spec.arguments.parameters.0.value + - src: + event: "calendar-gateway:example-with-interval" + dest: spec.arguments.parameters.1.value diff --git a/examples/sensors/multi-trigger-sensor.yaml b/examples/sensors/multi-trigger-sensor.yaml index 8ce78fdb47..278ec3d952 100644 --- a/examples/sensors/multi-trigger-sensor.yaml +++ b/examples/sensors/multi-trigger-sensor.yaml @@ -4,6 +4,9 @@ metadata: name: nats-multi-trigger-sensor labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -17,7 +20,7 @@ spec: http: port: "9300" dependencies: - - name: "webhook-gateway-http:foo" + - name: "webhook-gateway:example" triggers: - template: name: multi-trigger-workflow-1 diff --git a/examples/sensors/nats.yaml b/examples/sensors/nats.yaml index dacb76dcff..cd3ecb5be4 100644 --- a/examples/sensors/nats.yaml +++ b/examples/sensors/nats.yaml @@ -6,6 +6,9 @@ metadata: name: nats-sensor labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -19,7 +22,7 @@ spec: http: port: "9300" dependencies: - - name: "nats-gateway:foo" + - name: "nats-gateway:example-with-retry" triggers: - template: name: nats-workflow-trigger @@ -47,3 +50,7 @@ spec: image: docker/whalesay:latest command: [cowsay] args: ["{{inputs.parameters.message}}"] + resourceParameters: + - src: + event: "nats-gateway:example-with-retry" + dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/resource.yaml b/examples/sensors/resource.yaml index d13123140c..6eb4449cef 100644 --- a/examples/sensors/resource.yaml +++ b/examples/sensors/resource.yaml @@ -4,6 +4,9 @@ metadata: name: resource-sensor labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -17,7 +20,7 @@ spec: http: port: "9300" dependencies: - - name: "resource-gateway:workflow-success" + - name: "resource-gateway:example" triggers: - template: name: argo-workflow @@ -48,5 +51,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "resource-gateway:workflow-success" - dest: spec.arguments.parameters.0.value \ No newline at end of file + event: "resource-gateway:example" + dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/slack.yaml b/examples/sensors/slack.yaml index a1c6a6f0e5..bdd8a483aa 100644 --- a/examples/sensors/slack.yaml +++ b/examples/sensors/slack.yaml @@ -4,6 +4,9 @@ metadata: name: slack-sensor labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: containers: @@ -16,7 +19,7 @@ spec: http: port: "9300" dependencies: - - name: "slack-gateway:notification_1" + - name: "slack-gateway:example-1" triggers: - template: name: slack-workflow @@ -47,5 +50,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "slack-gateway:notification_1" + event: "slack-gateway:example-1" dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/storage-grid.yaml b/examples/sensors/storage-grid.yaml index d25aba1f78..5c51ab256c 100644 --- a/examples/sensors/storage-grid.yaml +++ b/examples/sensors/storage-grid.yaml @@ -4,6 +4,9 @@ metadata: name: storage-grid-watcher-sensor labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -13,7 +16,7 @@ spec: imagePullPolicy: Always serviceAccountName: argo-events-sa dependencies: - - name: "storage-grid-gateway:my_bucket" + - name: "storage-grid-gateway:example" eventProtocol: type: "HTTP" http: @@ -49,5 +52,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "storage-grid-gateway:my_bucket" + event: "storage-grid-gateway:example" dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/time-filter-webhook.yaml b/examples/sensors/time-filter-webhook.yaml index 2083f7e01e..9c6aa17180 100644 --- a/examples/sensors/time-filter-webhook.yaml +++ b/examples/sensors/time-filter-webhook.yaml @@ -4,6 +4,9 @@ metadata: name: webhook-time-filter-sensor labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -17,7 +20,7 @@ spec: http: port: "9300" dependencies: - - name: "webhook-gateway-http:foo" + - name: "webhook-gateway:example" filters: time: start: "22:14:05" diff --git a/examples/sensors/trello.yaml b/examples/sensors/trello.yaml deleted file mode 100644 index c8462df0f3..0000000000 --- a/examples/sensors/trello.yaml +++ /dev/null @@ -1,52 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Sensor -metadata: - name: trello-sensor - labels: - sensors.argoproj.io/sensor-controller-instanceid: argo-events -spec: - template: - spec: - containers: - - name: "sensor" - image: "argoproj/sensor" - imagePullPolicy: Always - serviceAccountName: argo-events-sa - eventProtocol: - type: "HTTP" - http: - port: "9300" - dependencies: - - name: "trello-gateway:notification_1" - triggers: - - template: - name: trello-workflow - group: argoproj.io - version: v1alpha1 - kind: Workflow - source: - inline: | - apiVersion: argoproj.io/v1alpha1 - kind: Workflow - metadata: - generateName: trello- - spec: - entrypoint: whalesay - arguments: - parameters: - - name: message - # this is the value that should be overridden - value: hello world - templates: - - name: whalesay - inputs: - parameters: - - name: message - container: - image: docker/whalesay:latest - command: [cowsay] - args: ["{{inputs.parameters.message}}"] - resourceParameters: - - src: - event: "trello-gateway:notification_1" - dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/trigger-gateway.yaml b/examples/sensors/trigger-gateway.yaml index b45730c369..d7b0d65e23 100644 --- a/examples/sensors/trigger-gateway.yaml +++ b/examples/sensors/trigger-gateway.yaml @@ -4,6 +4,9 @@ metadata: name: trigger-gateway-sensor labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -17,11 +20,11 @@ spec: http: port: "9300" dependencies: - - name: "webhook-gateway-http:foo" + - name: "webhook-gateway:example" # once sensor receives an event from webhook gateway, it will create an artifact gateway. triggers: - template: - name: artifact-gateway-configmap-trigger + name: artifact-event-source-trigger group: "" version: v1 kind: Configmap @@ -30,10 +33,12 @@ spec: apiVersion: v1 kind: Configmap metadata: - name: artifact-gateway-configmap + name: artifact-event-source + labels: + argo-events-event-source-version: v0.10 spec: data: - input: |- + example: |- bucket: name: input endpoint: minio-service.argo-events:9000 @@ -61,8 +66,10 @@ spec: name: artifact-gateway labels: gateways.argoproj.io/gateway-controller-instanceid: argo-events - gateway-name: "artifact-gateway" + argo-events-gateway-version: v0.10 spec: + type: "artifact" + eventSource: "artifact-event-source" processorPort: "9330" eventProtocol: type: "HTTP" @@ -84,10 +91,6 @@ spec: imagePullPolicy: "Always" command: ["/bin/artifact-gateway"] serviceAccountName: "argo-events-sa" - configMap: "artifact-gateway-configmap" - eventVersion: "1.0" - type: "artifact" watchers: sensors: - name: "artifact-sensor" - - name: "artifact-with-param-sensor" diff --git a/examples/sensors/trigger-source-configmap.yaml b/examples/sensors/trigger-source-configmap.yaml index eb165b68a9..a26dc4e4b7 100644 --- a/examples/sensors/trigger-source-configmap.yaml +++ b/examples/sensors/trigger-source-configmap.yaml @@ -4,6 +4,9 @@ metadata: name: trigger-source-configmap-sensor labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -17,7 +20,7 @@ spec: http: port: "9300" dependencies: - - name: "artifact-gateway:input" + - name: "artifact-gateway:example-1" triggers: - template: name: artifact-workflow-trigger diff --git a/examples/sensors/file-sensor.yaml b/examples/sensors/trigger-source-file.yaml similarity index 79% rename from examples/sensors/file-sensor.yaml rename to examples/sensors/trigger-source-file.yaml index a0da64dbd8..3a808656c7 100644 --- a/examples/sensors/file-sensor.yaml +++ b/examples/sensors/trigger-source-file.yaml @@ -3,7 +3,11 @@ kind: Sensor metadata: name: file-location-sensor labels: + # sensor controller with instanceId "argo-events" will process this sensor sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: diff --git a/examples/sensors/trigger-source-git.yaml b/examples/sensors/trigger-source-git.yaml index 1a74f5c3dd..94be97ffd6 100644 --- a/examples/sensors/trigger-source-git.yaml +++ b/examples/sensors/trigger-source-git.yaml @@ -4,6 +4,9 @@ metadata: name: trigger-source-git labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: diff --git a/examples/sensors/trigger-standard-k8s-resource.yaml b/examples/sensors/trigger-standard-k8s-resource.yaml index bc4c8b541f..442fe7bd19 100644 --- a/examples/sensors/trigger-standard-k8s-resource.yaml +++ b/examples/sensors/trigger-standard-k8s-resource.yaml @@ -4,6 +4,9 @@ metadata: name: webhook-sensor-http labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: diff --git a/examples/sensors/trigger-backoff.yaml b/examples/sensors/trigger-with-backoff.yaml similarity index 96% rename from examples/sensors/trigger-backoff.yaml rename to examples/sensors/trigger-with-backoff.yaml index 1c9f4f0cb5..3c2b539377 100644 --- a/examples/sensors/trigger-backoff.yaml +++ b/examples/sensors/trigger-with-backoff.yaml @@ -4,6 +4,9 @@ metadata: name: trigger-backoff labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: diff --git a/examples/sensors/url-sensor.yaml b/examples/sensors/url-sensor.yaml index 3cf744a6e3..c194d89a01 100644 --- a/examples/sensors/url-sensor.yaml +++ b/examples/sensors/url-sensor.yaml @@ -4,6 +4,9 @@ metadata: name: url-sensor labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: diff --git a/examples/sensors/webhook-nats-streaming.yaml b/examples/sensors/webhook-nats-streaming.yaml index 8a08666ec9..c954ae0834 100644 --- a/examples/sensors/webhook-nats-streaming.yaml +++ b/examples/sensors/webhook-nats-streaming.yaml @@ -4,6 +4,9 @@ metadata: name: webhook-nats-streaming labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -21,7 +24,7 @@ spec: clientId: "myclient1" deliverAllAvailable: true dependencies: - - name: "webhook-gateway-nats-streaming:foo" + - name: "webhook-gateway-streaming-nats:example" triggers: - template: name: argo-workflow @@ -52,5 +55,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "webhook-gateway-nats-streaming:foo" + event: "webhook-gateway-streaming-nats:example" dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/webhook-nats.yaml b/examples/sensors/webhook-nats.yaml index 342c281326..2bc03d9917 100644 --- a/examples/sensors/webhook-nats.yaml +++ b/examples/sensors/webhook-nats.yaml @@ -4,6 +4,9 @@ metadata: name: webhook-sensor labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -13,7 +16,7 @@ spec: imagePullPolicy: Always serviceAccountName: argo-events-sa dependencies: - - name: "webhook-gateway-nats:foo" + - name: "webhook-gateway-with-standard-nats:example" eventProtocol: type: "NATS" nats: @@ -49,5 +52,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "webhook-gateway-nats:foo" + event: "webhook-gateway-with-standard-nats:example" dest: spec.arguments.parameters.0.value diff --git a/examples/sensors/webhook-with-complete-payload.yaml b/examples/sensors/webhook-with-complete-payload.yaml deleted file mode 100644 index b6dc9bd521..0000000000 --- a/examples/sensors/webhook-with-complete-payload.yaml +++ /dev/null @@ -1,53 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Sensor -metadata: - name: webhook-with-complete-payload-sensor - labels: - sensors.argoproj.io/sensor-controller-instanceid: argo-events -spec: - template: - spec: - containers: - - name: "sensor" - image: "argoproj/sensor" - imagePullPolicy: Always - serviceAccountName: argo-events-sa - eventProtocol: - type: "NATS" - nats: - type: "Standard" - url: "nats://nats.argo-events:4222" - dependencies: - - name: "webhook-gateway-nats:foo" - triggers: - - template: - name: argo-workflow - group: argoproj.io - version: v1alpha1 - kind: Workflow - source: - inline: | - apiVersion: argoproj.io/v1alpha1 - kind: Workflow - metadata: - generateName: webhook- - spec: - entrypoint: whalesay - arguments: - parameters: - - name: message - # this is the value that should be overridden - value: hello world - templates: - - name: whalesay - inputs: - parameters: - - name: message - container: - image: docker/whalesay:latest - command: [cowsay] - args: ["{{inputs.parameters.message}}"] - resourceParameters: - - src: - event: "webhook-gateway-nats:foo" - dest: spec.arguments.parameters.0.value \ No newline at end of file diff --git a/examples/sensors/webhook-with-resource-param.yaml b/examples/sensors/webhook-with-resource-param.yaml deleted file mode 100644 index a054bfb92d..0000000000 --- a/examples/sensors/webhook-with-resource-param.yaml +++ /dev/null @@ -1,53 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Sensor -metadata: - name: webhook-with-resource-param-sensor - labels: - sensors.argoproj.io/sensor-controller-instanceid: argo-events -spec: - template: - spec: - containers: - - name: "sensor" - image: "argoproj/sensor" - imagePullPolicy: Always - serviceAccountName: argo-events-sa - eventProtocol: - type: "NATS" - nats: - type: "Standard" - url: "nats://nats.argo-events:4222" - dependencies: - - name: "webhook-gateway-nats:foo" - triggers: - - template: - name: argo-workflow - group: argoproj.io - version: v1alpha1 - kind: Workflow - source: - inline: | - apiVersion: argoproj.io/v1alpha1 - kind: Workflow - metadata: - generateName: webhook- - spec: - entrypoint: whalesay - arguments: - parameters: - - name: message - # this is the value that should be overridden - value: hello world - templates: - - name: whalesay - inputs: - parameters: - - name: message - container: - image: docker/whalesay:latest - command: [cowsay] - args: ["{{inputs.parameters.message}}"] - resourceParameters: - - src: - event: "webhook-gateway-nats:foo" - dest: spec.arguments.parameters.0.value \ No newline at end of file diff --git a/examples/sensors/webhook-http.yaml b/examples/sensors/webhook.yaml similarity index 84% rename from examples/sensors/webhook-http.yaml rename to examples/sensors/webhook.yaml index a7b9d37a19..9f48085ad2 100644 --- a/examples/sensors/webhook-http.yaml +++ b/examples/sensors/webhook.yaml @@ -1,9 +1,12 @@ apiVersion: argoproj.io/v1alpha1 kind: Sensor metadata: - name: webhook-sensor-http + name: webhook-sensor labels: sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: @@ -13,7 +16,7 @@ spec: imagePullPolicy: Always serviceAccountName: argo-events-sa dependencies: - - name: "webhook-gateway-http:foo" + - name: "webhook-gateway:example" eventProtocol: type: "HTTP" http: @@ -48,5 +51,5 @@ spec: args: ["{{inputs.parameters.message}}"] resourceParameters: - src: - event: "webhook-gateway-http:foo" + event: "webhook-gateway:example" dest: spec.arguments.parameters.0.value diff --git a/gateways/Dockerfile b/gateways/Dockerfile index 162feab577..60d6a9aa64 100644 --- a/gateways/Dockerfile +++ b/gateways/Dockerfile @@ -1,3 +1,3 @@ -FROM scratch +FROM centos:7 COPY dist/gateway-client /bin/ ENTRYPOINT [ "/bin/gateway-client" ] \ No newline at end of file diff --git a/gateways/common/validate.go b/gateways/common/validate.go index 90561e0644..feb662c40a 100644 --- a/gateways/common/validate.go +++ b/gateways/common/validate.go @@ -21,13 +21,19 @@ import ( "github.com/argoproj/argo-events/gateways" ) +const EventSourceDir = "../../../examples/event-sources" + var ( ErrNilEventSource = fmt.Errorf("event source can't be nil") ) -func ValidateGatewayEventSource(eventSource string, parseEventSource func(string) (interface{}, error), validateEventSource func(interface{}) error) (*gateways.ValidEventSource, error) { +func ValidateGatewayEventSource(eventSource *gateways.EventSource, version string, parseEventSource func(string) (interface{}, error), validateEventSource func(interface{}) error) (*gateways.ValidEventSource, error) { v := &gateways.ValidEventSource{} - es, err := parseEventSource(eventSource) + if eventSource.Version != version { + v.Reason = fmt.Sprintf("event source version mismatch. gateway expects %s version, and provided version is %s", version, eventSource.Version) + return v, nil + } + es, err := parseEventSource(eventSource.Data) if err != nil { v.Reason = fmt.Sprintf("failed to parse event source. err: %+v", err) return v, nil diff --git a/gateways/common/validate_test.go b/gateways/common/validate_test.go index 5f7f2e5271..a944870c80 100644 --- a/gateways/common/validate_test.go +++ b/gateways/common/validate_test.go @@ -1,8 +1,22 @@ +/* +Copyright 2018 BlackRock, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 common import ( - "fmt" - "github.com/ghodss/yaml" "github.com/smartystreets/goconvey/convey" "testing" ) @@ -13,29 +27,5 @@ type fakeEventSource struct { func TestValidateGatewayEventSource(t *testing.T) { convey.Convey("Given an event source, validate it", t, func() { - esStr := ` -msg: "hello" -` - es, err := ValidateGatewayEventSource(esStr, func(s string) (i interface{}, e error) { - t := &fakeEventSource{} - err := yaml.Unmarshal([]byte(esStr), t) - return t, err - }, func(i interface{}) error { - t, ok := i.(*fakeEventSource) - if !ok { - return fmt.Errorf("failed to cast to fake event source") - } - if t == nil { - return fmt.Errorf("event source cant be nil") - } - if t.Msg == "" { - return fmt.Errorf("msg can't be empty") - } - return nil - }) - - convey.So(err, convey.ShouldBeNil) - convey.So(es, convey.ShouldNotBeNil) - convey.So(es.IsValid, convey.ShouldEqual, true) }) } diff --git a/gateways/common/webhook.go b/gateways/common/webhook.go index 094935b42f..c59e26a752 100644 --- a/gateways/common/webhook.go +++ b/gateways/common/webhook.go @@ -19,6 +19,7 @@ package common import ( "fmt" "github.com/argoproj/argo-events/common" + "github.com/sirupsen/logrus" "net/http" "strconv" "strings" @@ -76,7 +77,7 @@ type activeServer struct { // Route contains common information for a route type Route struct { Webhook *Webhook - Logger *common.ArgoEventsLogger + Logger *logrus.Logger StartCh chan struct{} EventSource *gateways.EventSource } @@ -161,7 +162,7 @@ func startHttpServer(routeManager RouteManager, helper *WebhookHelper) { } else { err = r.Webhook.srv.ListenAndServeTLS(r.Webhook.ServerCertPath, r.Webhook.ServerKeyPath) } - r.Logger.WithEventSource(r.EventSource.Name).WithError(err).Error("http server stopped") + r.Logger.WithField(common.LabelEventSource, r.EventSource.Name).WithError(err).Error("http server stopped") if err != nil { errChan <- err } @@ -183,7 +184,12 @@ func activateRoute(routeManager RouteManager, helper *WebhookHelper) { helper.Mutex.Unlock() } - log := r.Logger.WithEventSource(r.EventSource.Name).WithPort(r.Webhook.Port).WithEndpoint(r.Webhook.Endpoint) + log := r.Logger.WithFields( + map[string]interface{}{ + common.LabelEventSource: r.EventSource.Name, + common.LabelPort: r.Webhook.Port, + common.LabelEndpoint: r.Webhook.Endpoint, + }) log.Info("adding route handler") if _, ok := helper.ActiveEndpoints[r.Webhook.Endpoint]; !ok { @@ -204,18 +210,18 @@ func processChannels(routeManager RouteManager, helper *WebhookHelper, eventStre for { select { case data := <-helper.ActiveEndpoints[r.Webhook.Endpoint].DataCh: - r.Logger.WithEventSource(r.EventSource.Name).Info("new event received, dispatching to gateway client") + r.Logger.WithField(common.LabelEventSource, r.EventSource.Name).Info("new event received, dispatching to gateway client") err := eventStream.Send(&gateways.Event{ Name: r.EventSource.Name, Payload: data, }) if err != nil { - r.Logger.WithEventSource(r.EventSource.Name).WithError(err).Error("failed to send event") + r.Logger.WithField(common.LabelEventSource, r.EventSource.Name).WithError(err).Error("failed to send event") return err } case <-eventStream.Context().Done(): - r.Logger.WithEventSource(r.EventSource.Name).Info("connection is closed by client") + r.Logger.WithField(common.LabelEventSource, r.EventSource.Name).Info("connection is closed by client") helper.RouteDeactivateChan <- routeManager return nil @@ -228,7 +234,7 @@ func processChannels(routeManager RouteManager, helper *WebhookHelper, eventStre func ProcessRoute(routeManager RouteManager, helper *WebhookHelper, eventStream gateways.Eventing_StartEventSourceServer) error { r := routeManager.GetRoute() - log := r.Logger.WithEventSource(r.EventSource.Name) + log := r.Logger.WithField(common.LabelEventSource, r.EventSource.Name) log.Info("validating the route") if err := validateRoute(routeManager.GetRoute()); err != nil { diff --git a/gateways/community/aws-sns/Dockerfile b/gateways/community/aws-sns/Dockerfile index dbcfa27bbe..07a8eaa4b5 100644 --- a/gateways/community/aws-sns/Dockerfile +++ b/gateways/community/aws-sns/Dockerfile @@ -1,3 +1,4 @@ -FROM scratch +FROM centos:7 +RUN yum -y install ca-certificates COPY dist/aws-sns-gateway /bin/ ENTRYPOINT [ "/bin/aws-sns-gateway" ] diff --git a/gateways/community/aws-sns/config.go b/gateways/community/aws-sns/config.go index f6e7e2c54f..17eff8a6cd 100644 --- a/gateways/community/aws-sns/config.go +++ b/gateways/community/aws-sns/config.go @@ -17,9 +17,9 @@ limitations under the License. package aws_sns import ( + "github.com/sirupsen/logrus" "time" - "github.com/argoproj/argo-events/common" gwcommon "github.com/argoproj/argo-events/gateways/common" snslib "github.com/aws/aws-sdk-go/service/sns" "github.com/ghodss/yaml" @@ -27,6 +27,8 @@ import ( "k8s.io/client-go/kubernetes" ) +const ArgoEventsEventSourceVersion = "v0.10" + const ( messageTypeSubscriptionConfirmation = "SubscriptionConfirmation" messageTypeNotification = "Notification" @@ -38,7 +40,7 @@ var ( // SNSEventSourceExecutor implements Eventing type SNSEventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger // Clientset is kubernetes client Clientset kubernetes.Interface // Namespace where gateway is deployed diff --git a/gateways/community/aws-sns/start.go b/gateways/community/aws-sns/start.go index a863f09c9b..0c0dae5c74 100644 --- a/gateways/community/aws-sns/start.go +++ b/gateways/community/aws-sns/start.go @@ -45,11 +45,13 @@ func (rc *RouteConfig) GetRoute() *gwcommon.Route { func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { r := rc.Route - logger := r.Logger. - WithEventSource(r.EventSource.Name). - WithEndpoint(r.Webhook.Endpoint). - WithPort(r.Webhook.Port). - WithHTTPMethod(request.Method) + logger := r.Logger.WithFields( + map[string]interface{}{ + common.LabelEventSource: r.EventSource.Name, + common.LabelEndpoint: r.Webhook.Endpoint, + common.LabelPort: r.Webhook.Port, + common.LabelHTTPMethod: r.Webhook.Method, + }) logger.Info("request received") @@ -99,11 +101,14 @@ func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Re func (rc *RouteConfig) PostStart() error { r := rc.Route - logger := r.Logger. - WithEventSource(r.EventSource.Name). - WithEndpoint(r.Webhook.Endpoint). - WithPort(r.Webhook.Port). - WithField("topic-arn", rc.snses.TopicArn) + logger := r.Logger.WithFields( + map[string]interface{}{ + common.LabelEventSource: r.EventSource.Name, + common.LabelEndpoint: r.Webhook.Endpoint, + common.LabelPort: r.Webhook.Port, + common.LabelHTTPMethod: r.Webhook.Method, + "topic-arn": rc.snses.TopicArn, + }) logger.Info("subscribing to sns topic") @@ -145,9 +150,9 @@ func (rc *RouteConfig) PostStop() error { func (ese *SNSEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { defer gateways.Recover(eventSource.Name) - log := ese.Log.WithEventSource(eventSource.Name) - + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("operating on event source") + config, err := parseEventSource(eventSource.Data) if err != nil { log.WithError(err).Error("failed to parse event source") diff --git a/gateways/community/aws-sns/validate.go b/gateways/community/aws-sns/validate.go index 9c3dac5938..3f38fb64d8 100644 --- a/gateways/community/aws-sns/validate.go +++ b/gateways/community/aws-sns/validate.go @@ -25,7 +25,7 @@ import ( // ValidateEventSource validates gateway event source func (ese *SNSEventSourceExecutor) ValidateEventSource(ctx context.Context, es *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(es.Data, parseEventSource, validateSNSConfig) + return gwcommon.ValidateGatewayEventSource(es, ArgoEventsEventSourceVersion, parseEventSource, validateSNSConfig) } func validateSNSConfig(config interface{}) error { diff --git a/gateways/community/aws-sns/validate_test.go b/gateways/community/aws-sns/validate_test.go index 85bfb39295..4809bb2b6d 100644 --- a/gateways/community/aws-sns/validate_test.go +++ b/gateways/community/aws-sns/validate_test.go @@ -18,56 +18,41 @@ package aws_sns import ( "context" - "github.com/argoproj/argo-events/gateways" - "github.com/smartystreets/goconvey/convey" + "fmt" + "io/ioutil" "testing" -) -var ( - configKey = "testConfig" - configId = "1234" - validConfig = ` -hook: - endpoint: "/test" - port: "8080" - url: "myurl/test" -topicArn: "test-arn" -region: "us-east-1" -accessKey: - key: accesskey - name: sns -secretKey: - key: secretkey - name: sns -` - - invalidConfig = ` -endpoint: "/" -port: "8080" -` + "github.com/argoproj/argo-events/common" + "github.com/argoproj/argo-events/gateways" + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" + "github.com/smartystreets/goconvey/convey" + corev1 "k8s.io/api/core/v1" ) func TestSNSEventSourceExecutor_ValidateEventSource(t *testing.T) { - convey.Convey("Given a valid sns event source spec, parse it and make sure no error occurs", t, func() { - ese := &SNSEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: validConfig, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) - - convey.Convey("Given an invalid sns event source spec, parse it and make sure error occurs", t, func() { + convey.Convey("Given sns event source spec, parse it and make sure no error occurs", t, func() { ese := &SNSEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: invalidConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + content, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", gwcommon.EventSourceDir, "aws-sns.yaml")) + convey.So(err, convey.ShouldBeNil) + + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/community/aws-sqs/Dockerfile b/gateways/community/aws-sqs/Dockerfile index b4098cf8bc..7eadf4ed65 100644 --- a/gateways/community/aws-sqs/Dockerfile +++ b/gateways/community/aws-sqs/Dockerfile @@ -1,3 +1,4 @@ -FROM scratch +FROM centos:7 +RUN yum -y install ca-certificates COPY dist/aws-sqs-gateway /bin/ ENTRYPOINT ["/bin/aws-sqs-gateway"] diff --git a/gateways/community/aws-sqs/config.go b/gateways/community/aws-sqs/config.go index 61662be69b..1c7f418ff1 100644 --- a/gateways/community/aws-sqs/config.go +++ b/gateways/community/aws-sqs/config.go @@ -17,15 +17,17 @@ limitations under the License. package aws_sqs import ( - "github.com/argoproj/argo-events/common" "github.com/ghodss/yaml" + "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" "k8s.io/client-go/kubernetes" ) +const ArgoEventsEventSourceVersion = "v0.10" + // SQSEventSourceExecutor implements Eventing type SQSEventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger // Clientset is kubernetes client Clientset kubernetes.Interface // Namespace where gateway is deployed diff --git a/gateways/community/aws-sqs/start.go b/gateways/community/aws-sqs/start.go index 26c3b9d879..f42e52b16c 100644 --- a/gateways/community/aws-sqs/start.go +++ b/gateways/community/aws-sqs/start.go @@ -17,6 +17,7 @@ limitations under the License. package aws_sqs import ( + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/aws/aws-sdk-go/aws" @@ -25,8 +26,11 @@ import ( // StartEventSource starts an event source func (ese *SQSEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { - log := ese.Log.WithEventSource(eventSource.Name) + defer gateways.Recover(eventSource.Name) + + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("activating event source") + config, err := parseEventSource(eventSource.Data) if err != nil { log.WithError(err).Error("failed to parse event source") @@ -44,8 +48,6 @@ func (ese *SQSEventSourceExecutor) StartEventSource(eventSource *gateways.EventS // listenEvents fires an event when interval completes and item is processed from queue. func (ese *SQSEventSourceExecutor) listenEvents(s *sqsEventSource, eventSource *gateways.EventSource, dataCh chan []byte, errorCh chan error, doneCh chan struct{}) { - defer gateways.Recover(eventSource.Name) - creds, err := gwcommon.GetAWSCreds(ese.Clientset, ese.Namespace, s.AccessKey, s.SecretKey) if err != nil { errorCh <- err @@ -80,7 +82,7 @@ func (ese *SQSEventSourceExecutor) listenEvents(s *sqsEventSource, eventSource * WaitTimeSeconds: aws.Int64(s.WaitTimeSeconds), }) if err != nil { - ese.Log.WithEventSource(eventSource.Name).WithError(err).Error("failed to process item from queue, waiting for next timeout") + ese.Log.WithField(common.LabelEventSource, eventSource.Name).WithError(err).Error("failed to process item from queue, waiting for next timeout") continue } diff --git a/gateways/community/aws-sqs/validate.go b/gateways/community/aws-sqs/validate.go index 5f5043dd68..207a18969c 100644 --- a/gateways/community/aws-sqs/validate.go +++ b/gateways/community/aws-sqs/validate.go @@ -26,7 +26,7 @@ import ( // ValidateEventSource validates gateway event source func (ese *SQSEventSourceExecutor) ValidateEventSource(ctx context.Context, es *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(es.Data, parseEventSource, validateSQSConfig) + return gwcommon.ValidateGatewayEventSource(es, ArgoEventsEventSourceVersion, parseEventSource, validateSQSConfig) } func validateSQSConfig(config interface{}) error { diff --git a/gateways/community/aws-sqs/validate_test.go b/gateways/community/aws-sqs/validate_test.go index 31cf0538c6..2abeac0ea1 100644 --- a/gateways/community/aws-sqs/validate_test.go +++ b/gateways/community/aws-sqs/validate_test.go @@ -18,58 +18,41 @@ package aws_sqs import ( "context" - "github.com/argoproj/argo-events/gateways" - "github.com/smartystreets/goconvey/convey" + "fmt" + "io/ioutil" "testing" -) -var ( - configKey = "testConfig" - configId = "1234" - validConfig = ` -region: "us-east-1" -accessKey: - key: accesskey - name: sns -secretKey: - key: secretkey - name: sns -queue: "test-queue" -waitTimeSeconds: 10 -` - - invalidConfig = ` -region: "us-east-1" -accessKey: - key: accesskey - name: sns -secretKey: - key: secretkey - name: sns -` + "github.com/argoproj/argo-events/common" + "github.com/argoproj/argo-events/gateways" + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" + "github.com/smartystreets/goconvey/convey" + corev1 "k8s.io/api/core/v1" ) func TestSQSEventSourceExecutor_ValidateEventSource(t *testing.T) { convey.Convey("Given a valid sqsEventSource event source spec, parse it and make sure no error occurs", t, func() { ese := &SQSEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: validConfig, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) - - convey.Convey("Given an invalid sqsEventSource event source spec, parse it and make sure error occurs", t, func() { - ese := &SQSEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: invalidConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + content, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", gwcommon.EventSourceDir, "aws-sqs.yaml")) + convey.So(err, convey.ShouldBeNil) + + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/community/gcp-pubsub/Dockerfile b/gateways/community/gcp-pubsub/Dockerfile index 4120e7eea2..ae1b64dc8e 100644 --- a/gateways/community/gcp-pubsub/Dockerfile +++ b/gateways/community/gcp-pubsub/Dockerfile @@ -1,7 +1,4 @@ -FROM alpine:3.9 as alpine -RUN apk add -U --no-cache ca-certificates - -FROM scratch +FROM centos:7 +RUN yum -y install ca-certificates COPY dist/gcp-pubsub-gateway /bin/ -COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ ENTRYPOINT [ "/bin/gcp-pubsub-gateway" ] diff --git a/gateways/community/gcp-pubsub/config.go b/gateways/community/gcp-pubsub/config.go index 2e82e4bb93..ee02ce5ef8 100644 --- a/gateways/community/gcp-pubsub/config.go +++ b/gateways/community/gcp-pubsub/config.go @@ -17,13 +17,15 @@ limitations under the License. package pubsub import ( - "github.com/argoproj/argo-events/common" "github.com/ghodss/yaml" + "github.com/sirupsen/logrus" ) +const ArgoEventsEventSourceVersion = "v0.10" + // GcpPubSubEventSourceExecutor implements Eventing type GcpPubSubEventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger } // pubSubEventSource contains configuration to subscribe to GCP PubSub topic diff --git a/gateways/community/gcp-pubsub/start.go b/gateways/community/gcp-pubsub/start.go index 21c16f66be..68b0203e1c 100644 --- a/gateways/community/gcp-pubsub/start.go +++ b/gateways/community/gcp-pubsub/start.go @@ -17,10 +17,9 @@ limitations under the License. package pubsub import ( - "context" - "fmt" - "cloud.google.com/go/pubsub" + "context" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" "google.golang.org/api/option" ) @@ -29,9 +28,9 @@ import ( func (ese *GcpPubSubEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { defer gateways.Recover(eventSource.Name) - log := ese.Log.WithEventSource(eventSource.Name) - + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) ese.Log.Info("operating on event source") + config, err := parseEventSource(eventSource.Data) if err != nil { log.WithError(err).Info("failed to parse event source") @@ -52,7 +51,7 @@ func (ese *GcpPubSubEventSourceExecutor) StartEventSource(eventSource *gateways. func (ese *GcpPubSubEventSourceExecutor) listenEvents(ctx context.Context, sc *pubSubEventSource, eventSource *gateways.EventSource, dataCh chan []byte, errorCh chan error, doneCh chan struct{}) { // Create a new topic with the given name. - logger := ese.Log.WithEventSource(eventSource.Name).WithField("topic", sc.Topic) + logger := ese.Log.WithField(common.LabelEventSource, eventSource.Name).WithField("topic", sc.Topic) client, err := pubsub.NewClient(ctx, sc.ProjectID, option.WithCredentialsFile(sc.CredentialsFile)) if err != nil { @@ -68,7 +67,7 @@ func (ese *GcpPubSubEventSourceExecutor) listenEvents(ctx context.Context, sc *p } logger.Info("subscribing to GCP PubSub topic") - sub, err := client.CreateSubscription(ctx, fmt.Sprintf("%v-%v", eventSource.Name, eventSource.Id), + sub, err := client.CreateSubscription(ctx, eventSource.Id, pubsub.SubscriptionConfig{Topic: topic}) if err != nil { errorCh <- err diff --git a/gateways/community/gcp-pubsub/validate.go b/gateways/community/gcp-pubsub/validate.go index f81c167e43..b8b57760d1 100644 --- a/gateways/community/gcp-pubsub/validate.go +++ b/gateways/community/gcp-pubsub/validate.go @@ -27,7 +27,7 @@ import ( // ValidateEventSource validates gateway event source func (ese *GcpPubSubEventSourceExecutor) ValidateEventSource(ctx context.Context, es *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(es.Data, parseEventSource, validatePubSubConfig) + return gwcommon.ValidateGatewayEventSource(es, ArgoEventsEventSourceVersion, parseEventSource, validatePubSubConfig) } func validatePubSubConfig(config interface{}) error { diff --git a/gateways/community/gcp-pubsub/validate_test.go b/gateways/community/gcp-pubsub/validate_test.go index 841041f60d..707b77752d 100644 --- a/gateways/community/gcp-pubsub/validate_test.go +++ b/gateways/community/gcp-pubsub/validate_test.go @@ -18,45 +18,42 @@ package pubsub import ( "context" - "github.com/argoproj/argo-events/gateways" - "github.com/smartystreets/goconvey/convey" + "fmt" + "io/ioutil" "testing" -) -var ( - configKey = "testConfig" - configId = "1234" - validConfig = ` -projectID: "1234" -topic: "test" -` - invalidConfig = ` -projectID: "1234" -` + "github.com/argoproj/argo-events/common" + "github.com/argoproj/argo-events/gateways" + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" + "github.com/smartystreets/goconvey/convey" + corev1 "k8s.io/api/core/v1" ) func TestGcpPubSubEventSourceExecutor_ValidateEventSource(t *testing.T) { convey.Convey("Given a valid gcp pub-sub event source spec, parse it and make sure no error occurs", t, func() { ese := &GcpPubSubEventSourceExecutor{} - - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: validConfig, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) - - convey.Convey("Given an invalid gcp pub-sub event source spec, parse it and make sure error occurs", t, func() { - ese := &GcpPubSubEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: invalidConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + content, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", gwcommon.EventSourceDir, "gcp-pubsub.yaml")) + convey.So(err, convey.ShouldBeNil) + + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.Println(valid.Reason) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/community/github/config.go b/gateways/community/github/config.go index ffb658efa1..cfcfb7af25 100644 --- a/gateways/community/github/config.go +++ b/gateways/community/github/config.go @@ -17,17 +17,19 @@ limitations under the License. package github import ( - "github.com/argoproj/argo-events/common" gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/ghodss/yaml" "github.com/google/go-github/github" + "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" "k8s.io/client-go/kubernetes" ) +const ArgoEventsEventSourceVersion = "v0.10" + // GithubEventSourceExecutor implements ConfigExecutor type GithubEventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger // Clientset is kubernetes client Clientset kubernetes.Interface // Namespace where gateway is deployed diff --git a/gateways/community/github/start.go b/gateways/community/github/start.go index 5907d22334..a9563a1098 100644 --- a/gateways/community/github/start.go +++ b/gateways/community/github/start.go @@ -144,7 +144,7 @@ func (rc *RouteConfig) PostStart() error { } rc.hook = hook - rc.route.Logger.WithEventSource(rc.route.EventSource.Name).Info("github hook created") + rc.route.Logger.WithField(common.LabelEventSource, rc.route.EventSource.Name).Info("github hook created") return nil } @@ -155,7 +155,7 @@ func (rc *RouteConfig) PostStop() error { if _, err := rc.client.Repositories.DeleteHook(ctx, rc.ges.Owner, rc.ges.Repository, *rc.hook.ID); err != nil { return fmt.Errorf("failed to delete hook. err: %+v", err) } - rc.route.Logger.WithEventSource(rc.route.EventSource.Name).Info("github hook deleted") + rc.route.Logger.WithField(common.LabelEventSource, rc.route.EventSource.Name).Info("github hook deleted") return nil } @@ -163,9 +163,9 @@ func (rc *RouteConfig) PostStop() error { func (ese *GithubEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { defer gateways.Recover(eventSource.Name) - log := ese.Log.WithEventSource(eventSource.Name) - + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("operating on event source") + config, err := parseEventSource(eventSource.Data) if err != nil { log.WithError(err).Error("failed to parse event source") @@ -209,10 +209,12 @@ func parseValidateRequest(r *http.Request, secret []byte) ([]byte, error) { func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { r := rc.route - logger := r.Logger. - WithEventSource(r.EventSource.Name). - WithEndpoint(r.Webhook.Endpoint). - WithPort(r.Webhook.Port) + logger := r.Logger.WithFields( + map[string]interface{}{ + common.LabelEventSource: r.EventSource.Name, + common.LabelEndpoint: r.Webhook.Endpoint, + common.LabelPort: r.Webhook.Port, + }) logger.Info("request received") diff --git a/gateways/community/github/tokenauth.go b/gateways/community/github/tokenauth.go index f389a8bdb3..41571606d9 100644 --- a/gateways/community/github/tokenauth.go +++ b/gateways/community/github/tokenauth.go @@ -1,3 +1,16 @@ +/* +Copyright 2018 KompiTech GmbH +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 github import "net/http" diff --git a/gateways/community/github/validate.go b/gateways/community/github/validate.go index 4812e86498..ee5f70a6fb 100644 --- a/gateways/community/github/validate.go +++ b/gateways/community/github/validate.go @@ -22,7 +22,7 @@ import ( // Validate validates github gateway configuration func (ese *GithubEventSourceExecutor) ValidateEventSource(ctx context.Context, es *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(es.Data, parseEventSource, validateGithub) + return gwcommon.ValidateGatewayEventSource(es, ArgoEventsEventSourceVersion, parseEventSource, validateGithub) } func validateGithub(config interface{}) error { diff --git a/gateways/community/github/validate_test.go b/gateways/community/github/validate_test.go index 15ba48bf25..5059b9c9e8 100644 --- a/gateways/community/github/validate_test.go +++ b/gateways/community/github/validate_test.go @@ -1,60 +1,58 @@ +/* +Copyright 2018 BlackRock, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 github import ( "context" - "github.com/argoproj/argo-events/gateways" - "github.com/smartystreets/goconvey/convey" + "fmt" + "io/ioutil" "testing" -) -var ( - configKey = "testConfig" - configId = "1234" - goodConfig = ` -id: 1234 -hook: - endpoint: "/push" - port: "12000" - url: "http://webhook-gateway-svc" -owner: "asd" -repository: "dsa" -events: -- PushEvents -apiToken: - key: accesskey - name: githab-access -` - - badConfig = ` -events: -- PushEvents -accessToken: - key: accesskey - name: gitlab-access -` + "github.com/argoproj/argo-events/common" + "github.com/argoproj/argo-events/gateways" + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" + "github.com/smartystreets/goconvey/convey" + corev1 "k8s.io/api/core/v1" ) func TestValidateGithubEventSource(t *testing.T) { - convey.Convey("Given a valid github event source spec, parse it and make sure no error occurs", t, func() { + convey.Convey("Given github event source spec, parse it and make sure no error occurs", t, func() { ese := &GithubEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: goodConfig, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) + content, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", gwcommon.EventSourceDir, "github.yaml")) + convey.So(err, convey.ShouldBeNil) - convey.Convey("Given an invalid github event source spec, parse it and make sure error occurs", t, func() { - ese := &GithubEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: badConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/community/gitlab/Dockerfile b/gateways/community/gitlab/Dockerfile index 46cbe0f2ff..5f5d454da2 100644 --- a/gateways/community/gitlab/Dockerfile +++ b/gateways/community/gitlab/Dockerfile @@ -1,3 +1,4 @@ -FROM scratch +FROM centos:7 +RUN yum -y install ca-certificates COPY dist/gitlab-gateway /bin/ ENTRYPOINT [ "/bin/gitlab-gateway" ] \ No newline at end of file diff --git a/gateways/community/gitlab/config.go b/gateways/community/gitlab/config.go index 0fd642f4af..7a777995b1 100644 --- a/gateways/community/gitlab/config.go +++ b/gateways/community/gitlab/config.go @@ -17,16 +17,18 @@ limitations under the License. package gitlab import ( - "github.com/argoproj/argo-events/common" gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/ghodss/yaml" + "github.com/sirupsen/logrus" "github.com/xanzy/go-gitlab" "k8s.io/client-go/kubernetes" ) +const ArgoEventsEventSourceVersion = "v0.10" + // GitlabEventSourceExecutor implements ConfigExecutor type GitlabEventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger // Clientset is kubernetes client Clientset kubernetes.Interface // Namespace where gateway is deployed @@ -45,8 +47,6 @@ type RouteConfig struct { // gitlabEventSource contains information to setup a gitlab project integration type gitlabEventSource struct { - // Webhook Id - Id int `json:"id"` // Webhook Hook *gwcommon.Webhook `json:"hook"` // ProjectId is the id of project for which integration needs to setup diff --git a/gateways/community/gitlab/start.go b/gateways/community/gitlab/start.go index d5890f8b11..4020ffc535 100644 --- a/gateways/community/gitlab/start.go +++ b/gateways/community/gitlab/start.go @@ -86,7 +86,7 @@ func (rc *RouteConfig) PostStart() error { } rc.hook = hook - rc.route.Logger.WithEventSource(rc.route.EventSource.Name).Info("gitlab hook created") + rc.route.Logger.WithField(common.LabelEventSource, rc.route.EventSource.Name).Info("gitlab hook created") return nil } @@ -94,20 +94,24 @@ func (rc *RouteConfig) PostStop() error { if _, err := rc.client.Projects.DeleteProjectHook(rc.ges.ProjectId, rc.hook.ID); err != nil { return fmt.Errorf("failed to delete hook. err: %+v", err) } - rc.route.Logger.WithEventSource(rc.route.EventSource.Name).Info("gitlab hook deleted") + rc.route.Logger.WithField(common.LabelEventSource, rc.route.EventSource.Name).Info("gitlab hook deleted") return nil } // routeActiveHandler handles new route func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { - log := rc.route.Logger. - WithEventSource(rc.route.EventSource.Name). - WithEndpoint(rc.route.Webhook.Endpoint). - WithPort(rc.route.Webhook.Port) + r := rc.route + + log := r.Logger.WithFields( + map[string]interface{}{ + common.LabelEventSource: r.EventSource.Name, + common.LabelEndpoint: r.Webhook.Endpoint, + common.LabelPort: r.Webhook.Port, + }) log.Info("request received") - if !helper.ActiveEndpoints[rc.route.Webhook.Endpoint].Active { + if !helper.ActiveEndpoints[r.Webhook.Endpoint].Active { log.Info("endpoint is not active") common.SendErrorResponse(writer, "") return @@ -120,7 +124,7 @@ func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Re return } - helper.ActiveEndpoints[rc.route.Webhook.Endpoint].DataCh <- body + helper.ActiveEndpoints[r.Webhook.Endpoint].DataCh <- body log.Info("request successfully processed") common.SendSuccessResponse(writer, "") } @@ -129,7 +133,7 @@ func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Re func (ese *GitlabEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { defer gateways.Recover(eventSource.Name) - log := ese.Log.WithEventSource(eventSource.Name) + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("operating on event source") config, err := parseEventSource(eventSource.Data) diff --git a/gateways/community/gitlab/validate.go b/gateways/community/gitlab/validate.go index 8e5dd0e556..b03eaf2dc8 100644 --- a/gateways/community/gitlab/validate.go +++ b/gateways/community/gitlab/validate.go @@ -23,7 +23,7 @@ import ( // ValidateEventSource validates gitlab gateway event source func (ese *GitlabEventSourceExecutor) ValidateEventSource(ctx context.Context, es *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(es.Data, parseEventSource, validateGitlab) + return gwcommon.ValidateGatewayEventSource(es, ArgoEventsEventSourceVersion, parseEventSource, validateGitlab) } func validateGitlab(config interface{}) error { @@ -31,9 +31,6 @@ func validateGitlab(config interface{}) error { if g == nil { return gwcommon.ErrNilEventSource } - if g.Id == 0 { - return fmt.Errorf("hook id must be not be zero") - } if g.ProjectId == "" { return fmt.Errorf("project id can't be empty") } diff --git a/gateways/community/gitlab/validate_test.go b/gateways/community/gitlab/validate_test.go index fa3e331ec1..c8ad5c89cf 100644 --- a/gateways/community/gitlab/validate_test.go +++ b/gateways/community/gitlab/validate_test.go @@ -18,58 +18,42 @@ package gitlab import ( "context" - "github.com/argoproj/argo-events/gateways" - "github.com/smartystreets/goconvey/convey" + "fmt" + "io/ioutil" "testing" -) -var ( - configKey = "testConfig" - configId = "1234" - validConfig = ` -id: 1234 -hook: - endpoint: "/push" - port: "12000" - url: "http://webhook-gateway-gateway-svc/push" -projectId: "28" -event: "PushEvents" -accessToken: - key: accesskey - name: gitlab-access -enableSSLVerification: false -gitlabBaseUrl: "http://gitlab.com/" -` - invalidConfig = ` -url: "http://webhook-gateway-gateway-svc/push" -event: "PushEvents" -accessToken: - key: accesskey - name: gitlab-access -` + "github.com/argoproj/argo-events/common" + "github.com/argoproj/argo-events/gateways" + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" + "github.com/smartystreets/goconvey/convey" + corev1 "k8s.io/api/core/v1" ) func TestValidateGitlabEventSource(t *testing.T) { - convey.Convey("Given a valid gitlab event source spec, parse it and make sure no error occurs", t, func() { - ese := &GitlabEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: validConfig, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) - - convey.Convey("Given an invalid gitlab event source spec, parse it and make sure error occurs", t, func() { + convey.Convey("Given a gitlab event source spec, parse it and make sure no error occurs", t, func() { ese := &GitlabEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: invalidConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + content, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", gwcommon.EventSourceDir, "gitlab.yaml")) + convey.So(err, convey.ShouldBeNil) + + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.Println(valid.Reason) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/community/hdfs/config.go b/gateways/community/hdfs/config.go index 0e286e435c..95480ceac7 100644 --- a/gateways/community/hdfs/config.go +++ b/gateways/community/hdfs/config.go @@ -2,7 +2,7 @@ package hdfs import ( "errors" - "github.com/argoproj/argo-events/common" + "github.com/sirupsen/logrus" gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/ghodss/yaml" @@ -10,9 +10,11 @@ import ( "k8s.io/client-go/kubernetes" ) +const ArgoEventsEventSourceVersion = "v0.10" + // EventSourceExecutor implements Eventing type EventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger // Clientset is kubernetes client Clientset kubernetes.Interface // Namespace where gateway is deployed diff --git a/gateways/community/hdfs/start.go b/gateways/community/hdfs/start.go index 22c6c25e80..fb68c90df3 100644 --- a/gateways/community/hdfs/start.go +++ b/gateways/community/hdfs/start.go @@ -3,6 +3,7 @@ package hdfs import ( "encoding/json" "fmt" + "github.com/argoproj/argo-events/common" "os" "path/filepath" "regexp" @@ -37,7 +38,7 @@ func (w *WatchableHDFS) GetFileID(fi os.FileInfo) interface{} { func (ese *EventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { defer gateways.Recover(eventSource.Name) - ese.Log.WithEventSource(eventSource.Name).Info("activating event source") + ese.Log.WithField(common.LabelEventSource, eventSource.Name).Info("activating event source") config, err := parseEventSource(eventSource.Data) if err != nil { return err @@ -56,7 +57,7 @@ func (ese *EventSourceExecutor) StartEventSource(eventSource *gateways.EventSour func (ese *EventSourceExecutor) listenEvents(config *GatewayConfig, eventSource *gateways.EventSource, dataCh chan []byte, errorCh chan error, doneCh chan struct{}) { defer gateways.Recover(eventSource.Name) - log := ese.Log.WithEventSource(eventSource.Name) + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) hdfsConfig, err := createHDFSConfig(ese.Clientset, ese.Namespace, &config.GatewayClientConfig) if err != nil { diff --git a/gateways/community/hdfs/validate.go b/gateways/community/hdfs/validate.go index b1f0d0a61e..068245b543 100644 --- a/gateways/community/hdfs/validate.go +++ b/gateways/community/hdfs/validate.go @@ -29,7 +29,7 @@ import ( // ValidateEventSource validates gateway event source func (ese *EventSourceExecutor) ValidateEventSource(ctx context.Context, es *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(es.Data, parseEventSource, validateGatewayConfig) + return gwcommon.ValidateGatewayEventSource(es, ArgoEventsEventSourceVersion, parseEventSource, validateGatewayConfig) } func validateGatewayConfig(config interface{}) error { diff --git a/gateways/community/hdfs/validate_test.go b/gateways/community/hdfs/validate_test.go index 8d6c265273..3c03f52eb0 100644 --- a/gateways/community/hdfs/validate_test.go +++ b/gateways/community/hdfs/validate_test.go @@ -2,56 +2,41 @@ package hdfs import ( "context" + "fmt" + "io/ioutil" "testing" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" "github.com/smartystreets/goconvey/convey" -) - -var ( - configKey = "testConfig" - configId = "1234" - goodConfig = ` -directory: "/tmp/" -type: "CREATE" -path: x.txt -addresses: -- my-hdfs-namenode-0.my-hdfs-namenode.default.svc.cluster.local:8020 -- my-hdfs-namenode-1.my-hdfs-namenode.default.svc.cluster.local:8020 -hdfsUser: root -` - - badConfig = ` -directory: "/tmp/" -type: "CREATE" -addresses: -- my-hdfs-namenode-0.my-hdfs-namenode.default.svc.cluster.local:8020 -- my-hdfs-namenode-1.my-hdfs-namenode.default.svc.cluster.local:8020 -hdfsUser: roots -` + corev1 "k8s.io/api/core/v1" ) func TestValidateEventSource(t *testing.T) { - convey.Convey("Given a valid github event source spec, parse it and make sure no error occurs", t, func() { + convey.Convey("Given a hdfs event source spec, parse it and make sure no error occurs", t, func() { ese := &EventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: goodConfig, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) + content, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", gwcommon.EventSourceDir, "hdfs.yaml")) + convey.So(err, convey.ShouldBeNil) - convey.Convey("Given an invalid github event source spec, parse it and make sure error occurs", t, func() { - ese := &EventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: badConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/community/slack/config.go b/gateways/community/slack/config.go index 57f700a594..34c7b5ccca 100644 --- a/gateways/community/slack/config.go +++ b/gateways/community/slack/config.go @@ -17,20 +17,22 @@ limitations under the License. package slack import ( - "github.com/argoproj/argo-events/common" gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/ghodss/yaml" + "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" "k8s.io/client-go/kubernetes" ) +const ArgoEventsEventSourceVersion = "v0.10" + // SlackEventSourceExecutor implements Eventing type SlackEventSourceExecutor struct { // Clientset is kubernetes client Clientset kubernetes.Interface // Namespace where gateway is deployed Namespace string - Log *common.ArgoEventsLogger + Log *logrus.Logger } type RouteConfig struct { diff --git a/gateways/community/slack/start.go b/gateways/community/slack/start.go index b0eba872b1..9cd37d064a 100644 --- a/gateways/community/slack/start.go +++ b/gateways/community/slack/start.go @@ -44,11 +44,13 @@ func (rc *RouteConfig) GetRoute() *gwcommon.Route { func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { r := rc.route - log := r.Logger. - WithEventSource(r.EventSource.Name). - WithEndpoint(r.Webhook.Endpoint). - WithPort(r.Webhook.Port). - WithHTTPMethod(request.Method) + log := r.Logger.WithFields( + map[string]interface{}{ + common.LabelEventSource: r.EventSource.Name, + common.LabelEndpoint: r.Webhook.Endpoint, + common.LabelPort: r.Webhook.Port, + common.LabelHTTPMethod: r.Webhook.Method, + }) log.Info("request received") @@ -114,7 +116,7 @@ func (rc *RouteConfig) PostStop() error { func (ese *SlackEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { defer gateways.Recover(eventSource.Name) - log := ese.Log.WithEventSource(eventSource.Name) + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("operating on event source") config, err := parseEventSource(eventSource.Data) diff --git a/gateways/community/slack/validate.go b/gateways/community/slack/validate.go index 5c54cee246..4c9637d82a 100644 --- a/gateways/community/slack/validate.go +++ b/gateways/community/slack/validate.go @@ -26,7 +26,7 @@ import ( // ValidateEventSource validates gateway event source func (ese *SlackEventSourceExecutor) ValidateEventSource(ctx context.Context, es *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(es.Data, parseEventSource, validateSlack) + return gwcommon.ValidateGatewayEventSource(es, ArgoEventsEventSourceVersion, parseEventSource, validateSlack) } func validateSlack(config interface{}) error { diff --git a/gateways/community/slack/validate_test.go b/gateways/community/slack/validate_test.go index ea04d555fa..32a54fc035 100644 --- a/gateways/community/slack/validate_test.go +++ b/gateways/community/slack/validate_test.go @@ -18,51 +18,41 @@ package slack import ( "context" + "fmt" + "io/ioutil" "testing" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" "github.com/smartystreets/goconvey/convey" -) - -var ( - configKey = "testConfig" - configId = "1234" - validConfig = ` -hook: - endpoint: "/" - port: "8080" - url: "testurl" -token: - name: fake-token - key: fake -` - - invalidConfig = ` -endpoint: "/" -` + corev1 "k8s.io/api/core/v1" ) func TestValidateStorageGridEventSource(t *testing.T) { - convey.Convey("Given a valid slack event source spec, parse it and make sure no error occurs", t, func() { - ese := &SlackEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: validConfig, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) - - convey.Convey("Given an invalid slack event source spec, parse it and make sure error occurs", t, func() { + convey.Convey("Given a slack event source spec, parse it and make sure no error occurs", t, func() { ese := &SlackEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: invalidConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + content, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", gwcommon.EventSourceDir, "slack.yaml")) + convey.So(err, convey.ShouldBeNil) + + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/community/storagegrid/config.go b/gateways/community/storagegrid/config.go index 1d25eef0ef..2ac7440bc3 100644 --- a/gateways/community/storagegrid/config.go +++ b/gateways/community/storagegrid/config.go @@ -17,17 +17,19 @@ limitations under the License. package storagegrid import ( + "github.com/sirupsen/logrus" "net/http" "time" - "github.com/argoproj/argo-events/common" gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/ghodss/yaml" ) +const ArgoEventsEventSourceVersion = "v0.10" + // StorageGridEventSourceExecutor implements Eventing type StorageGridEventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger } type RouteConfig struct { diff --git a/gateways/community/storagegrid/start.go b/gateways/community/storagegrid/start.go index 4897b60888..1d7d62c1b6 100644 --- a/gateways/community/storagegrid/start.go +++ b/gateways/community/storagegrid/start.go @@ -91,7 +91,7 @@ func (rc *RouteConfig) GetRoute() *gwcommon.Route { func (ese *StorageGridEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { defer gateways.Recover(eventSource.Name) - log := ese.Log.WithEventSource(eventSource.Name) + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("operating on event source") config, err := parseEventSource(eventSource.Data) @@ -122,13 +122,17 @@ func (rc *RouteConfig) PostStop() error { // RouteHandler handles new route func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { - log := rc.route.Logger. - WithEventSource(rc.route.EventSource.Name). - WithEndpoint(rc.route.Webhook.Endpoint). - WithPort(rc.route.Webhook.Port). - WithHTTPMethod(request.Method) + r := rc.route - if !helper.ActiveEndpoints[rc.route.Webhook.Endpoint].Active { + log := r.Logger.WithFields( + map[string]interface{}{ + common.LabelEventSource: r.EventSource.Name, + common.LabelEndpoint: r.Webhook.Endpoint, + common.LabelPort: r.Webhook.Port, + common.LabelHTTPMethod: r.Webhook.Method, + }) + + if !helper.ActiveEndpoints[r.Webhook.Endpoint].Active { log.Warn("inactive route") common.SendErrorResponse(writer, "") return diff --git a/gateways/community/storagegrid/validate.go b/gateways/community/storagegrid/validate.go index e23bd84908..45c1e2b380 100644 --- a/gateways/community/storagegrid/validate.go +++ b/gateways/community/storagegrid/validate.go @@ -24,7 +24,7 @@ import ( // ValidateEventSource validates gateway event source func (ese *StorageGridEventSourceExecutor) ValidateEventSource(ctx context.Context, es *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(es.Data, parseEventSource, validateStorageGrid) + return gwcommon.ValidateGatewayEventSource(es, ArgoEventsEventSourceVersion, parseEventSource, validateStorageGrid) } func validateStorageGrid(config interface{}) error { diff --git a/gateways/community/storagegrid/validate_test.go b/gateways/community/storagegrid/validate_test.go index cbf56fcb23..1cdc2a367e 100644 --- a/gateways/community/storagegrid/validate_test.go +++ b/gateways/community/storagegrid/validate_test.go @@ -18,57 +18,41 @@ package storagegrid import ( "context" - "github.com/smartystreets/goconvey/convey" + "fmt" + "io/ioutil" "testing" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" -) - -var ( - configKey = "testConfig" - configId = "1234" - validConfig = ` -hook: - endpoint: "/" - port: "8080" - url: "testurl" -events: - - "ObjectCreated:Put" -filter: - suffix: ".txt" - prefix: "hello-" -` - - invalidConfig = ` -events: - - "ObjectCreated:Put" -filter: - suffix: ".txt" - prefix: "hello-" -` + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" + "github.com/smartystreets/goconvey/convey" + corev1 "k8s.io/api/core/v1" ) func TestValidateStorageGridEventSource(t *testing.T) { - convey.Convey("Given a valid storage grid event source spec, parse it and make sure no error occurs", t, func() { - ese := &StorageGridEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: validConfig, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) - - convey.Convey("Given an invalid storage grid event source spec, parse it and make sure error occurs", t, func() { + convey.Convey("Given a storage grid event source spec, parse it and make sure no error occurs", t, func() { ese := &StorageGridEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: invalidConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + content, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", gwcommon.EventSourceDir, "storage-grid.yaml")) + convey.So(err, convey.ShouldBeNil) + + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/config.go b/gateways/config.go index 9a510fc492..5e20028d00 100644 --- a/gateways/config.go +++ b/gateways/config.go @@ -19,6 +19,7 @@ package gateways import ( "context" "fmt" + "github.com/sirupsen/logrus" "os" "github.com/nats-io/go-nats" @@ -37,7 +38,7 @@ import ( // GatewayConfig provides a generic event source for a gateway type GatewayConfig struct { // Log provides fast and simple logger dedicated to JSON output - Log *common.ArgoEventsLogger + Log *logrus.Logger // Clientset is client for kubernetes API Clientset kubernetes.Interface // Name is gateway name @@ -72,8 +73,8 @@ type GatewayConfig struct { // EventSourceContext contains information of a event source for gateway to run. type EventSourceContext struct { - // Data holds the actual event source - Data *EventSourceData + // Source holds the actual event source + Source *EventSource // Ctx contains context for the connection Ctx context.Context // Cancel upon invocation cancels the connection context @@ -84,16 +85,6 @@ type EventSourceContext struct { Conn *grpc.ClientConn } -// EventSourceData holds the actual event source -type EventSourceData struct { - // Unique ID for event source - ID string `json:"id"` - // Src contains name of the event source - Src string `json:"src"` - // Config contains the event source - Config string `json:"config"` -} - // GatewayEvent is the internal representation of an event. type GatewayEvent struct { // Src is source of event @@ -138,7 +129,11 @@ func NewGatewayConfiguration() *GatewayConfig { } gc := &GatewayConfig{ - Log: common.NewArgoEventsLogger().WithGatewayName(name).WithNamespace(namespace), + Log: common.NewArgoEventsLogger().WithFields( + map[string]interface{}{ + common.LabelGatewayName: gw.Name, + common.LabelNamespace: gw.Namespace, + }).Logger, Clientset: clientset, Namespace: namespace, Name: name, diff --git a/gateways/core/artifact/config.go b/gateways/core/artifact/config.go index 213c1a5047..fa1f3b6ba4 100644 --- a/gateways/core/artifact/config.go +++ b/gateways/core/artifact/config.go @@ -17,15 +17,17 @@ limitations under the License. package artifact import ( - "github.com/argoproj/argo-events/common" apicommon "github.com/argoproj/argo-events/pkg/apis/common" "github.com/ghodss/yaml" + "github.com/sirupsen/logrus" "k8s.io/client-go/kubernetes" ) +const ArgoEventsEventSourceVersion = "v0.10" + // S3EventSourceExecutor implements Eventing type S3EventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger // Clientset is kubernetes client Clientset kubernetes.Interface // Namespace where gateway is deployed diff --git a/gateways/core/artifact/start.go b/gateways/core/artifact/start.go index ec727398bc..d163a6a812 100644 --- a/gateways/core/artifact/start.go +++ b/gateways/core/artifact/start.go @@ -18,6 +18,7 @@ package artifact import ( "encoding/json" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" apicommon "github.com/argoproj/argo-events/pkg/apis/common" @@ -27,9 +28,9 @@ import ( // StartEventSource activates an event source and streams back events func (ese *S3EventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { - log := ese.Log.WithEventSource(eventSource.Name) - + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("activating event source") + config, err := parseEventSource(eventSource.Data) if err != nil { log.WithError(err).Error("failed to parse event source") @@ -48,7 +49,7 @@ func (ese *S3EventSourceExecutor) StartEventSource(eventSource *gateways.EventSo // listenEvents listens to minio bucket notifications func (ese *S3EventSourceExecutor) listenEvents(a *apicommon.S3Artifact, eventSource *gateways.EventSource, dataCh chan []byte, errorCh chan error, doneCh chan struct{}) { defer gateways.Recover(eventSource.Name) - log := ese.Log.WithEventSource(eventSource.Name) + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("operating on event source") diff --git a/gateways/core/artifact/validate.go b/gateways/core/artifact/validate.go index 6a18372a32..c73f24fd52 100644 --- a/gateways/core/artifact/validate.go +++ b/gateways/core/artifact/validate.go @@ -28,7 +28,7 @@ import ( // ValidateEventSource validates a s3 event source func (ese *S3EventSourceExecutor) ValidateEventSource(ctx context.Context, eventSource *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(eventSource.Data, parseEventSource, validateArtifact) + return gwcommon.ValidateGatewayEventSource(eventSource, ArgoEventsEventSourceVersion, parseEventSource, validateArtifact) } // validates an artifact diff --git a/gateways/core/artifact/validate_test.go b/gateways/core/artifact/validate_test.go index 989f0a6a02..ca7b7a3d90 100644 --- a/gateways/core/artifact/validate_test.go +++ b/gateways/core/artifact/validate_test.go @@ -18,66 +18,41 @@ package artifact import ( "context" + "fmt" + "io/ioutil" "testing" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" "github.com/smartystreets/goconvey/convey" -) - -var ( - configKey = "testConfig" - configId = "1234" - configValue = ` -bucket: - name: input -endpoint: minio-service.argo-events:9000 -events: - - s3:ObjectCreated:Put -filter: - prefix: "" - suffix: "" -insecure: true -accessKey: - key: accesskey - name: artifacts-minio -secretKey: - key: secretkey - name: artifacts-minio -` + corev1 "k8s.io/api/core/v1" ) func TestValidateS3EventSource(t *testing.T) { - convey.Convey("Given a valid S3 artifact spec, parse the spec and make sure no error occurs", t, func() { - ese := &S3EventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Data: configValue, - Id: configId, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) - - convey.Convey("Given an invalid S3 artifact spec, parse it and error should occur", t, func() { + convey.Convey("Given a S3 artifact spec, parse the spec and make sure no error occurs", t, func() { ese := &S3EventSourceExecutor{} - invalidS3Artifact := ` -s3EventConfig: - bucket: input - endpoint: minio-service.argo-events:9000 - events: - - s3:ObjectCreated:Put - filter: - prefix: "" - suffix: "" -insecure: true -` - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Id: configId, - Name: configKey, - Data: invalidS3Artifact, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + content, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", gwcommon.EventSourceDir, "artifact.yaml")) + convey.So(err, convey.ShouldBeNil) + + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/core/calendar/config.go b/gateways/core/calendar/config.go index d3eae0b38a..f65ddb8181 100644 --- a/gateways/core/calendar/config.go +++ b/gateways/core/calendar/config.go @@ -17,15 +17,17 @@ limitations under the License. package calendar import ( - "github.com/argoproj/argo-events/common" + "github.com/sirupsen/logrus" "time" "github.com/ghodss/yaml" ) +const ArgoEventsEventSourceVersion = "v0.10" + // CalendarEventSourceExecutor implements Eventing type CalendarEventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger } // calSchedule describes a time based dependency. One of the fields (schedule, interval, or recurrence) must be passed. diff --git a/gateways/core/calendar/start.go b/gateways/core/calendar/start.go index 21aedb4a14..8b389ad138 100644 --- a/gateways/core/calendar/start.go +++ b/gateways/core/calendar/start.go @@ -31,7 +31,7 @@ type Next func(time.Time) time.Time // StartEventSource starts an event source func (ese *CalendarEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { - log := ese.Log.WithEventSource(eventSource.Name) + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("activating event source") config, err := parseEventSource(eventSource.Data) @@ -114,7 +114,11 @@ func (ese *CalendarEventSourceExecutor) listenEvents(cal *calSchedule, eventSour for { t := next(lastT) timer := time.After(time.Until(t)) - ese.Log.WithEventSource(eventSource.Name).WithTime(t.UTC().String()).Info("expected next calendar event") + ese.Log.WithFields( + map[string]interface{}{ + common.LabelEventSource: eventSource.Name, + common.LabelTime: t.UTC().String(), + }).Info("expected next calendar event") select { case tx := <-timer: lastT = tx diff --git a/gateways/core/calendar/validate.go b/gateways/core/calendar/validate.go index 1a00af6f54..9d90e20fe5 100644 --- a/gateways/core/calendar/validate.go +++ b/gateways/core/calendar/validate.go @@ -26,7 +26,7 @@ import ( // ValidateEventSource validates gateway event source func (ese *CalendarEventSourceExecutor) ValidateEventSource(ctx context.Context, eventSource *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(eventSource.Data, parseEventSource, validateSchedule) + return gwcommon.ValidateGatewayEventSource(eventSource, ArgoEventsEventSourceVersion, parseEventSource, validateSchedule) } func validateSchedule(config interface{}) error { diff --git a/gateways/core/calendar/validate_test.go b/gateways/core/calendar/validate_test.go index 9bce874a83..6f54d616b0 100644 --- a/gateways/core/calendar/validate_test.go +++ b/gateways/core/calendar/validate_test.go @@ -18,42 +18,41 @@ package calendar import ( "context" - "github.com/smartystreets/goconvey/convey" + "fmt" + "io/ioutil" "testing" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" -) - -var ( - configKey = "testConfig" - configId = "1234" - configValue = ` -schedule: 30 * * * * -` + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" + "github.com/smartystreets/goconvey/convey" + corev1 "k8s.io/api/core/v1" ) func TestValidateCalendarEventSource(t *testing.T) { - convey.Convey("Given a valid calendar spec, parse it and make sure no error occurs", t, func() { - ese := &CalendarEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: configValue, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) - - convey.Convey("Given an invalid calendar spec, parse it and make sure error occurs", t, func() { + convey.Convey("Given a calendar spec, parse it and make sure no error occurs", t, func() { ese := &CalendarEventSourceExecutor{} - invalidConfig := "" - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: invalidConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + content, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", gwcommon.EventSourceDir, "calendar.yaml")) + convey.So(err, convey.ShouldBeNil) + + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/core/file/config.go b/gateways/core/file/config.go index 4a0f64829c..4605da43bb 100644 --- a/gateways/core/file/config.go +++ b/gateways/core/file/config.go @@ -17,14 +17,16 @@ limitations under the License. package file import ( - "github.com/argoproj/argo-events/common" gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/ghodss/yaml" + "github.com/sirupsen/logrus" ) +const ArgoEventsEventSourceVersion = "v0.10" + // FileEventSourceExecutor implements Eventing type FileEventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger } // fileWatcher contains configuration information for this gateway diff --git a/gateways/core/file/start.go b/gateways/core/file/start.go index ff4c26b322..6782949518 100644 --- a/gateways/core/file/start.go +++ b/gateways/core/file/start.go @@ -19,6 +19,7 @@ package file import ( "encoding/json" "fmt" + "github.com/argoproj/argo-events/common" "regexp" "strings" @@ -29,9 +30,9 @@ import ( // StartEventSource starts an event source func (ese *FileEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { - log := ese.Log.WithEventSource(eventSource.Name) - + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("activating event source") + config, err := parseEventSource(eventSource.Data) if err != nil { log.WithError(err).Error("failed to parse event source") @@ -50,7 +51,7 @@ func (ese *FileEventSourceExecutor) StartEventSource(eventSource *gateways.Event func (ese *FileEventSourceExecutor) listenEvents(fwc *fileWatcher, eventSource *gateways.EventSource, dataCh chan []byte, errorCh chan error, doneCh chan struct{}) { defer gateways.Recover(eventSource.Name) - log := ese.Log.WithEventSource(eventSource.Name) + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) // create new fs watcher watcher, err := fsnotify.NewWatcher() diff --git a/gateways/core/file/validate.go b/gateways/core/file/validate.go index ada546b2c7..4a1d27fa79 100644 --- a/gateways/core/file/validate.go +++ b/gateways/core/file/validate.go @@ -26,7 +26,7 @@ import ( // ValidateEventSource validates gateway event source func (ese *FileEventSourceExecutor) ValidateEventSource(ctx context.Context, es *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(es.Data, parseEventSource, validateFileWatcher) + return gwcommon.ValidateGatewayEventSource(es, ArgoEventsEventSourceVersion, parseEventSource, validateFileWatcher) } func validateFileWatcher(config interface{}) error { diff --git a/gateways/core/file/validate_test.go b/gateways/core/file/validate_test.go index 4bc98a4129..f97a61420b 100644 --- a/gateways/core/file/validate_test.go +++ b/gateways/core/file/validate_test.go @@ -18,46 +18,41 @@ package file import ( "context" + "fmt" + "io/ioutil" "testing" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" "github.com/smartystreets/goconvey/convey" -) - -var ( - configKey = "testConfig" - configId = "1234" - configValue = ` -directory: "/bin/" -type: CREATE -path: x.txt -` + corev1 "k8s.io/api/core/v1" ) func TestValidateFileEventSource(t *testing.T) { - convey.Convey("Given a valid file event source spec, parse it and make sure no error occurs", t, func() { - ese := &FileEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: configValue, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) - - convey.Convey("Given an invalid file event source spec, parse it and make sure error occurs", t, func() { + convey.Convey("Given a file event source spec, parse it and make sure no error occurs", t, func() { ese := &FileEventSourceExecutor{} - invalidConfig := ` -type: CREATE -path: x.txt` - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: invalidConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + content, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", gwcommon.EventSourceDir, "file.yaml")) + convey.So(err, convey.ShouldBeNil) + + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/core/resource/config.go b/gateways/core/resource/config.go index b42213cac1..dc0175c502 100644 --- a/gateways/core/resource/config.go +++ b/gateways/core/resource/config.go @@ -17,16 +17,18 @@ limitations under the License. package resource import ( - "github.com/argoproj/argo-events/common" "github.com/ghodss/yaml" + "github.com/sirupsen/logrus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/rest" ) +const ArgoEventsEventSourceVersion = "v0.10" + // ResourceEventSourceExecutor implements Eventing type ResourceEventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger // K8RestConfig is kubernetes cluster config K8RestConfig *rest.Config } diff --git a/gateways/core/resource/start.go b/gateways/core/resource/start.go index d12ef529fc..a7e3dca437 100644 --- a/gateways/core/resource/start.go +++ b/gateways/core/resource/start.go @@ -19,6 +19,7 @@ package resource import ( "encoding/json" "fmt" + "github.com/argoproj/argo-events/common" "strings" "github.com/argoproj/argo-events/gateways" @@ -34,8 +35,9 @@ import ( // StartEventSource starts an event source func (ese *ResourceEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { - log := ese.Log.WithEventSource(eventSource.Name) + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("operating on event source") + config, err := parseEventSource(eventSource.Data) if err != nil { log.WithError(err).Error("failed to parse event source") @@ -60,7 +62,7 @@ func (ese *ResourceEventSourceExecutor) listenEvents(res *resource, eventSource options.LabelSelector = labels.Set(res.Filter.Labels).AsSelector().String() } - ese.Log.WithEventSource(eventSource.Name).Info("starting to watch to resource notifications") + ese.Log.WithField(common.LabelEventSource, eventSource.Name).Info("starting to watch to resource notifications") resourceList, err := ese.discoverResources(res) if err != nil { @@ -128,7 +130,7 @@ func (ese *ResourceEventSourceExecutor) listenEvents(res *resource, eventSource } func (ese *ResourceEventSourceExecutor) watchObjectChannel(watcher watch.Interface, res *resource, eventSource *gateways.EventSource, resourceObjects map[string]string, dataCh chan []byte, errorCh chan error, watchCh chan struct{}, doneCh chan struct{}) { - log := ese.Log.WithEventSource(eventSource.Name) + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) for { select { case item := <-watcher.ResultChan(): @@ -223,7 +225,7 @@ func (ese *ResourceEventSourceExecutor) resolveGroupVersion(obj *resource) strin // helper method to return a flag indicating if the object passed the client side filters func (ese *ResourceEventSourceExecutor) passFilters(esName string, obj *unstructured.Unstructured, filter *ResourceFilter) bool { - log := ese.Log.WithEventSource(esName) + log := ese.Log.WithField(common.LabelEventSource, esName) // no filters are applied. if filter == nil { diff --git a/gateways/core/resource/validate.go b/gateways/core/resource/validate.go index 1f1e4be04c..60a2c59253 100644 --- a/gateways/core/resource/validate.go +++ b/gateways/core/resource/validate.go @@ -26,7 +26,7 @@ import ( // ValidateEventSource validates gateway event source func (ese *ResourceEventSourceExecutor) ValidateEventSource(ctx context.Context, es *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(es.Data, parseEventSource, validateResource) + return gwcommon.ValidateGatewayEventSource(es, ArgoEventsEventSourceVersion, parseEventSource, validateResource) } func validateResource(config interface{}) error { diff --git a/gateways/core/resource/validate_test.go b/gateways/core/resource/validate_test.go index 50fcd6e10b..120855a43a 100644 --- a/gateways/core/resource/validate_test.go +++ b/gateways/core/resource/validate_test.go @@ -18,56 +18,42 @@ package resource import ( "context" - "github.com/smartystreets/goconvey/convey" + "fmt" + "io/ioutil" "testing" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" -) - -var ( - configKey = "testConfig" - configId = "1234" - configValue = ` -namespace: "argo-events" -group: "argoproj.io" -version: "v1alpha1" -kind: "Workflow" -filter: - labels: - workflows.argoproj.io/phase: Succeeded - name: "my-workflow" -` + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" + "github.com/smartystreets/goconvey/convey" + corev1 "k8s.io/api/core/v1" ) func TestValidateResourceEventSource(t *testing.T) { - convey.Convey("Given a valid resource event source spec, parse it and make sure no error occurs", t, func() { - ese := &ResourceEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: configValue, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) - - convey.Convey("Given an invalid resource event source spec, parse it and make sure error occurs", t, func() { + convey.Convey("Given a resource event source spec, parse it and make sure no error occurs", t, func() { ese := &ResourceEventSourceExecutor{} - invalidConfig := ` -group: "argoproj.io" -version: "v1alpha1" -filter: - labels: - workflows.argoproj.io/phase: Succeeded - name: "my-workflow" -` - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: invalidConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + content, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", gwcommon.EventSourceDir, "resource.yaml")) + convey.So(err, convey.ShouldBeNil) + + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.Println(valid.Reason) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/core/stream/amqp/config.go b/gateways/core/stream/amqp/config.go index 8fe75f0356..508a93f0df 100644 --- a/gateways/core/stream/amqp/config.go +++ b/gateways/core/stream/amqp/config.go @@ -19,13 +19,15 @@ package amqp import ( "github.com/argoproj/argo-events/common" "github.com/ghodss/yaml" + "github.com/sirupsen/logrus" amqplib "github.com/streadway/amqp" - "k8s.io/apimachinery/pkg/util/wait" ) +const ArgoEventsEventSourceVersion = "v0.10" + // AMQPEventSourceExecutor implements Eventing type AMQPEventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger } // amqp contains configuration required to connect to rabbitmq service and process messages @@ -40,7 +42,7 @@ type amqp struct { // Routing key for bindings RoutingKey string `json:"routingKey"` // Backoff holds parameters applied to connection. - Backoff *wait.Backoff `json:"backoff,omitempty"` + Backoff *common.Backoff `json:"backoff,omitempty"` // Connection manages the serialization and deserialization of frames from IO // and dispatches the frames to the appropriate channel. conn *amqplib.Connection diff --git a/gateways/core/stream/amqp/start.go b/gateways/core/stream/amqp/start.go index cee5e4040c..c351507d9b 100644 --- a/gateways/core/stream/amqp/start.go +++ b/gateways/core/stream/amqp/start.go @@ -18,13 +18,15 @@ package amqp import ( "fmt" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" amqplib "github.com/streadway/amqp" + "k8s.io/apimachinery/pkg/util/wait" ) // StartEventSource starts an event source func (ese *AMQPEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { - log := ese.Log.WithEventSource(eventSource.Name) + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("operating on event source") config, err := parseEventSource(eventSource.Data) @@ -68,7 +70,12 @@ func getDelivery(ch *amqplib.Channel, a *amqp) (<-chan amqplib.Delivery, error) func (ese *AMQPEventSourceExecutor) listenEvents(a *amqp, eventSource *gateways.EventSource, dataCh chan []byte, errorCh chan error, doneCh chan struct{}) { defer gateways.Recover(eventSource.Name) - if err := gateways.Connect(a.Backoff, func() error { + if err := gateways.Connect(&wait.Backoff{ + Steps: a.Backoff.Steps, + Factor: a.Backoff.Factor, + Duration: a.Backoff.Duration, + Jitter: a.Backoff.Jitter, + }, func() error { var err error a.conn, err = amqplib.Dial(a.URL) if err != nil { @@ -92,7 +99,7 @@ func (ese *AMQPEventSourceExecutor) listenEvents(a *amqp, eventSource *gateways. return } - log := ese.Log.WithEventSource(eventSource.Name) + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("starting to subscribe to messages") for { diff --git a/gateways/core/stream/amqp/validate.go b/gateways/core/stream/amqp/validate.go index 4b526e4386..a1d018ad2e 100644 --- a/gateways/core/stream/amqp/validate.go +++ b/gateways/core/stream/amqp/validate.go @@ -25,7 +25,7 @@ import ( // ValidateEventSource validates gateway event source func (ese *AMQPEventSourceExecutor) ValidateEventSource(ctx context.Context, es *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(es.Data, parseEventSource, validateAMQP) + return gwcommon.ValidateGatewayEventSource(es, ArgoEventsEventSourceVersion, parseEventSource, validateAMQP) } func validateAMQP(config interface{}) error { diff --git a/gateways/core/stream/amqp/validate_test.go b/gateways/core/stream/amqp/validate_test.go index b993522076..f8e91b8d90 100644 --- a/gateways/core/stream/amqp/validate_test.go +++ b/gateways/core/stream/amqp/validate_test.go @@ -18,49 +18,41 @@ package amqp import ( "context" + "fmt" + "io/ioutil" "testing" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" "github.com/smartystreets/goconvey/convey" -) - -var ( - configKey = "testConfig" - configId = "1234" - configValue = ` -url: amqp://amqp.argo-events:5672 -exchangeName: fooExchangeName -exchangeType: fanout -routingKey: fooRoutingKey -` - invalidConfig = ` -url: amqp://amqp.argo-events:5672 -exchangeName: fooExchangeName -exchangeType: fanout -` + corev1 "k8s.io/api/core/v1" ) func TestValidateAMQPEventSource(t *testing.T) { - convey.Convey("Given a valid amqp event source spec, parse it and make sure no error occurs", t, func() { - ese := &AMQPEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: configValue, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) - - convey.Convey("Given an invalid amqp event source spec, parse it and make sure error occurs", t, func() { + convey.Convey("Given a amqp event source spec, parse it and make sure no error occurs", t, func() { ese := &AMQPEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: invalidConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + content, err := ioutil.ReadFile(fmt.Sprintf("../%s/%s", gwcommon.EventSourceDir, "amqp.yaml")) + convey.So(err, convey.ShouldBeNil) + + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/core/stream/kafka/config.go b/gateways/core/stream/kafka/config.go index cc314624fe..b1f5c3e442 100644 --- a/gateways/core/stream/kafka/config.go +++ b/gateways/core/stream/kafka/config.go @@ -20,12 +20,14 @@ import ( "github.com/Shopify/sarama" "github.com/argoproj/argo-events/common" "github.com/ghodss/yaml" - "k8s.io/apimachinery/pkg/util/wait" + "github.com/sirupsen/logrus" ) +const ArgoEventsEventSourceVersion = "v0.10" + // KafkaEventSourceExecutor implements Eventing type KafkaEventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger } // kafka defines configuration required to connect to kafka cluster @@ -37,7 +39,7 @@ type kafka struct { // Topic name Topic string `json:"topic"` // Backoff holds parameters applied to connection. - Backoff *wait.Backoff `json:"backoff,omitempty"` + Backoff *common.Backoff `json:"backoff,omitempty"` // Consumer manages PartitionConsumers which process Kafka messages from brokers. consumer sarama.Consumer } diff --git a/gateways/core/stream/kafka/start.go b/gateways/core/stream/kafka/start.go index b46b667383..2a678e0540 100644 --- a/gateways/core/stream/kafka/start.go +++ b/gateways/core/stream/kafka/start.go @@ -18,12 +18,11 @@ package kafka import ( "fmt" - "strconv" - - "github.com/argoproj/argo-events/common" - "github.com/Shopify/sarama" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" + "k8s.io/apimachinery/pkg/util/wait" + "strconv" ) func verifyPartitionAvailable(part int32, partitions []int32) bool { @@ -37,7 +36,7 @@ func verifyPartitionAvailable(part int32, partitions []int32) bool { // StartEventSource starts an event source func (ese *KafkaEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { - log := ese.Log.WithEventSource(eventSource.Name) + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("operating on event source") config, err := parseEventSource(eventSource.Data) @@ -58,9 +57,14 @@ func (ese *KafkaEventSourceExecutor) StartEventSource(eventSource *gateways.Even func (ese *KafkaEventSourceExecutor) listenEvents(k *kafka, eventSource *gateways.EventSource, dataCh chan []byte, errorCh chan error, doneCh chan struct{}) { defer gateways.Recover(eventSource.Name) - log := ese.Log.WithEventSource(eventSource.Name) + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) - if err := gateways.Connect(k.Backoff, func() error { + if err := gateways.Connect(&wait.Backoff{ + Steps: k.Backoff.Steps, + Jitter: k.Backoff.Jitter, + Duration: k.Backoff.Duration, + Factor: k.Backoff.Factor, + }, func() error { var err error k.consumer, err = sarama.NewConsumer([]string{k.URL}, nil) if err != nil { diff --git a/gateways/core/stream/kafka/validate.go b/gateways/core/stream/kafka/validate.go index 868d60e46b..2cd8c138f1 100644 --- a/gateways/core/stream/kafka/validate.go +++ b/gateways/core/stream/kafka/validate.go @@ -26,7 +26,7 @@ import ( // ValidateEventSource validates the gateway event source func (ese *KafkaEventSourceExecutor) ValidateEventSource(ctx context.Context, es *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(es.Data, parseEventSource, validateKafka) + return gwcommon.ValidateGatewayEventSource(es, ArgoEventsEventSourceVersion, parseEventSource, validateKafka) } func validateKafka(config interface{}) error { diff --git a/gateways/core/stream/kafka/validate_test.go b/gateways/core/stream/kafka/validate_test.go index 898de80a4b..b3678f73fa 100644 --- a/gateways/core/stream/kafka/validate_test.go +++ b/gateways/core/stream/kafka/validate_test.go @@ -18,46 +18,41 @@ package kafka import ( "context" + "fmt" + "io/ioutil" "testing" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" "github.com/smartystreets/goconvey/convey" -) - -var ( - configKey = "testConfig" - configId = "1234" - configValue = ` -url: kafka.argo-events:9092 -topic: foo -partition: "0" -` + corev1 "k8s.io/api/core/v1" ) func TestValidateKafkaEventSource(t *testing.T) { - convey.Convey("Given a valid kafka event source spec, parse it and make sure no error occurs", t, func() { - ese := &KafkaEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: configValue, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) - - convey.Convey("Given an invalid kafka event source spec, parse it and make sure error occurs", t, func() { + convey.Convey("Given a kafka event source spec, parse it and make sure no error occurs", t, func() { ese := &KafkaEventSourceExecutor{} - invalidConfig := ` -topic: foo -` - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: invalidConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + content, err := ioutil.ReadFile(fmt.Sprintf("../%s/%s", gwcommon.EventSourceDir, "kafka.yaml")) + convey.So(err, convey.ShouldBeNil) + + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/core/stream/mqtt/config.go b/gateways/core/stream/mqtt/config.go index 62e5d50de6..1bb2c4c6b3 100644 --- a/gateways/core/stream/mqtt/config.go +++ b/gateways/core/stream/mqtt/config.go @@ -20,12 +20,14 @@ import ( "github.com/argoproj/argo-events/common" mqttlib "github.com/eclipse/paho.mqtt.golang" "github.com/ghodss/yaml" - "k8s.io/apimachinery/pkg/util/wait" + "github.com/sirupsen/logrus" ) +const ArgoEventsEventSourceVersion = "v0.10" + // MqttEventSourceExecutor implements Eventing type MqttEventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger } // mqtt contains information to connect to MQTT broker @@ -37,7 +39,7 @@ type mqtt struct { // Client ID ClientId string `json:"clientId"` // Backoff holds parameters applied to connection. - Backoff *wait.Backoff `json:"backoff,omitempty"` + Backoff *common.Backoff `json:"backoff,omitempty"` // It is an MQTT client for communicating with an MQTT server client mqttlib.Client } diff --git a/gateways/core/stream/mqtt/start.go b/gateways/core/stream/mqtt/start.go index 70b246f425..eec63dacf6 100644 --- a/gateways/core/stream/mqtt/start.go +++ b/gateways/core/stream/mqtt/start.go @@ -20,11 +20,12 @@ import ( "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" mqttlib "github.com/eclipse/paho.mqtt.golang" + "k8s.io/apimachinery/pkg/util/wait" ) // StartEventSource starts an event source func (ese *MqttEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { - log := ese.Log.WithEventSource(eventSource.Name) + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("operating on event source") config, err := parseEventSource(eventSource.Data) @@ -45,10 +46,11 @@ func (ese *MqttEventSourceExecutor) StartEventSource(eventSource *gateways.Event func (ese *MqttEventSourceExecutor) listenEvents(m *mqtt, eventSource *gateways.EventSource, dataCh chan []byte, errorCh chan error, doneCh chan struct{}) { defer gateways.Recover(eventSource.Name) - log := ese.Log.WithEventSource(eventSource.Name).WithFields( + log := ese.Log.WithFields( map[string]interface{}{ - common.LabelURL: m.URL, - common.LabelClientID: m.ClientId, + common.LabelEventSource: eventSource.Name, + common.LabelURL: m.URL, + common.LabelClientID: m.ClientId, }, ) @@ -57,7 +59,12 @@ func (ese *MqttEventSourceExecutor) listenEvents(m *mqtt, eventSource *gateways. } opts := mqttlib.NewClientOptions().AddBroker(m.URL).SetClientID(m.ClientId) - if err := gateways.Connect(m.Backoff, func() error { + if err := gateways.Connect(&wait.Backoff{ + Factor: m.Backoff.Factor, + Duration: m.Backoff.Duration, + Jitter: m.Backoff.Jitter, + Steps: m.Backoff.Steps, + }, func() error { client := mqttlib.NewClient(opts) if token := client.Connect(); token.Wait() && token.Error() != nil { return token.Error() diff --git a/gateways/core/stream/mqtt/validate.go b/gateways/core/stream/mqtt/validate.go index 241105de44..f3a3a4d8b5 100644 --- a/gateways/core/stream/mqtt/validate.go +++ b/gateways/core/stream/mqtt/validate.go @@ -25,7 +25,7 @@ import ( // ValidateEventSource validates gateway event source func (ese *MqttEventSourceExecutor) ValidateEventSource(ctx context.Context, es *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(es.Data, parseEventSource, validateMQTT) + return gwcommon.ValidateGatewayEventSource(es, ArgoEventsEventSourceVersion, parseEventSource, validateMQTT) } func validateMQTT(config interface{}) error { diff --git a/gateways/core/stream/mqtt/validate_test.go b/gateways/core/stream/mqtt/validate_test.go index 69ab989cbe..d700b9d40b 100644 --- a/gateways/core/stream/mqtt/validate_test.go +++ b/gateways/core/stream/mqtt/validate_test.go @@ -18,48 +18,41 @@ package mqtt import ( "context" + "fmt" + "io/ioutil" "testing" - "github.com/smartystreets/goconvey/convey" - + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" -) - -var ( - configKey = "testConfig" - configId = "1234" - configValue = ` -url: tcp://mqtt.argo-events:1883 -topic: foo -clientId: 1 -` + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" + "github.com/smartystreets/goconvey/convey" + corev1 "k8s.io/api/core/v1" ) func TestValidateMqttEventSource(t *testing.T) { - convey.Convey("Given a valid mqtt event source spec, parse it and make sure no error occurs", t, func() { - ese := &MqttEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: configValue, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) - - convey.Convey("Given an invalid mqtt event source spec, parse it and make sure error occurs", t, func() { + convey.Convey("Given a mqtt event source spec, parse it and make sure no error occurs", t, func() { ese := &MqttEventSourceExecutor{} - invalidConfig := ` -url: tcp://mqtt.argo-events:1883 -topic: foo -` - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: invalidConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + content, err := ioutil.ReadFile(fmt.Sprintf("../%s/%s", gwcommon.EventSourceDir, "mqtt.yaml")) + convey.So(err, convey.ShouldBeNil) + + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/core/stream/nats/config.go b/gateways/core/stream/nats/config.go index 96dd4df101..4be21c0eca 100644 --- a/gateways/core/stream/nats/config.go +++ b/gateways/core/stream/nats/config.go @@ -20,12 +20,14 @@ import ( "github.com/argoproj/argo-events/common" "github.com/ghodss/yaml" natslib "github.com/nats-io/go-nats" - "k8s.io/apimachinery/pkg/util/wait" + "github.com/sirupsen/logrus" ) +const ArgoEventsEventSourceVersion = "v0.10" + // NatsEventSourceExecutor implements Eventing type NatsEventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger } // Nats contains configuration to connect to NATS cluster @@ -35,7 +37,7 @@ type natsConfig struct { // Subject name Subject string `json:"subject"` // Backoff holds parameters applied to connection. - Backoff *wait.Backoff `json:"backoff,omitempty"` + Backoff *common.Backoff `json:"backoff,omitempty"` // conn represents a bare connection to a nats-server. conn *natslib.Conn } diff --git a/gateways/core/stream/nats/start.go b/gateways/core/stream/nats/start.go index d37e1e5c91..4f6de230d4 100644 --- a/gateways/core/stream/nats/start.go +++ b/gateways/core/stream/nats/start.go @@ -20,13 +20,14 @@ import ( "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" natslib "github.com/nats-io/go-nats" + "k8s.io/apimachinery/pkg/util/wait" ) // StartEventSource starts an event source func (ese *NatsEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { - log := ese.Log.WithEventSource(eventSource.Name) - + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("operating on event source") + config, err := parseEventSource(eventSource.Data) if err != nil { log.WithError(err).Error("failed to parse event source") @@ -45,14 +46,20 @@ func (ese *NatsEventSourceExecutor) StartEventSource(eventSource *gateways.Event func (ese *NatsEventSourceExecutor) listenEvents(n *natsConfig, eventSource *gateways.EventSource, dataCh chan []byte, errorCh chan error, doneCh chan struct{}) { defer gateways.Recover(eventSource.Name) - log := ese.Log.WithEventSource(eventSource.Name).WithFields( + log := ese.Log.WithFields( map[string]interface{}{ - common.LabelURL: n.URL, - "subject": n.Subject, + common.LabelEventSource: eventSource.Name, + common.LabelURL: n.URL, + "subject": n.Subject, }, ) - if err := gateways.Connect(n.Backoff, func() error { + if err := gateways.Connect(&wait.Backoff{ + Steps: n.Backoff.Steps, + Jitter: n.Backoff.Jitter, + Duration: n.Backoff.Duration, + Factor: n.Backoff.Factor, + }, func() error { var err error if n.conn, err = natslib.Connect(n.URL); err != nil { return err diff --git a/gateways/core/stream/nats/validate.go b/gateways/core/stream/nats/validate.go index 4778265303..395ccb87b7 100644 --- a/gateways/core/stream/nats/validate.go +++ b/gateways/core/stream/nats/validate.go @@ -25,7 +25,7 @@ import ( // ValidateEventSource validates gateway event source func (ese *NatsEventSourceExecutor) ValidateEventSource(ctx context.Context, es *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(es.Data, parseEventSource, validateNATS) + return gwcommon.ValidateGatewayEventSource(es, ArgoEventsEventSourceVersion, parseEventSource, validateNATS) } func validateNATS(config interface{}) error { diff --git a/gateways/core/stream/nats/validate_test.go b/gateways/core/stream/nats/validate_test.go index b0c341ac3c..951294a5c5 100644 --- a/gateways/core/stream/nats/validate_test.go +++ b/gateways/core/stream/nats/validate_test.go @@ -18,45 +18,41 @@ package nats import ( "context" - "github.com/smartystreets/goconvey/convey" + "fmt" + "io/ioutil" "testing" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" -) - -var ( - configKey = "testConfig" - configId = "1234" - configValue = ` -url: natsConfig://natsConfig.argo-events:4222 -subject: foo -` + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" + "github.com/smartystreets/goconvey/convey" + corev1 "k8s.io/api/core/v1" ) func TestValidateNatsEventSource(t *testing.T) { - convey.Convey("Given a valid nats event source spec, parse it and make sure no error occurs", t, func() { - ese := &NatsEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: configValue, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) - - convey.Convey("Given an invalid nats event source spec, parse it and make sure error occurs", t, func() { + convey.Convey("Given a nats event source spec, parse it and make sure no error occurs", t, func() { ese := &NatsEventSourceExecutor{} - invalidConfig := ` -subject: foo -` - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: invalidConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) + content, err := ioutil.ReadFile(fmt.Sprintf("../%s/%s", gwcommon.EventSourceDir, "nats.yaml")) + convey.So(err, convey.ShouldBeNil) + + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) } diff --git a/gateways/core/webhook/config.go b/gateways/core/webhook/config.go index ef0c44cc05..8a7681f6fd 100644 --- a/gateways/core/webhook/config.go +++ b/gateways/core/webhook/config.go @@ -17,14 +17,16 @@ limitations under the License. package webhook import ( - "github.com/argoproj/argo-events/common" gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/ghodss/yaml" + "github.com/sirupsen/logrus" ) +const ArgoEventsEventSourceVersion = "v0.10" + // WebhookEventSourceExecutor implements Eventing type WebhookEventSourceExecutor struct { - Log *common.ArgoEventsLogger + Log *logrus.Logger } type RouteConfig struct { diff --git a/gateways/core/webhook/start.go b/gateways/core/webhook/start.go index 853e9f5113..615f19ac96 100644 --- a/gateways/core/webhook/start.go +++ b/gateways/core/webhook/start.go @@ -44,7 +44,13 @@ func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Re r := rc.Route - log := r.Logger.WithEventSource(r.EventSource.Name).WithEndpoint(r.Webhook.Endpoint).WithPort(r.Webhook.Port).WithHTTPMethod(request.Method) + log := r.Logger.WithFields( + map[string]interface{}{ + common.LabelEventSource: r.EventSource.Name, + common.LabelEndpoint: r.Webhook.Endpoint, + common.LabelPort: r.Webhook.Port, + common.LabelHTTPMethod: r.Webhook.Method, + }) log.Info("request received") @@ -92,7 +98,7 @@ func (rc *RouteConfig) PostStop() error { func (ese *WebhookEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { defer gateways.Recover(eventSource.Name) - log := ese.Log.WithEventSource(eventSource.Name) + log := ese.Log.WithField(common.LabelEventSource, eventSource.Name) log.Info("operating on event source") config, err := parseEventSource(eventSource.Data) diff --git a/gateways/core/webhook/validate.go b/gateways/core/webhook/validate.go index 29d1c359e4..65bc6eb5f1 100644 --- a/gateways/core/webhook/validate.go +++ b/gateways/core/webhook/validate.go @@ -19,6 +19,7 @@ package webhook import ( "context" "fmt" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" gwcommon "github.com/argoproj/argo-events/gateways/common" "net/http" @@ -26,7 +27,12 @@ import ( // ValidateEventSource validates webhook event source func (ese *WebhookEventSourceExecutor) ValidateEventSource(ctx context.Context, es *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(es.Data, parseEventSource, validateWebhook) + ese.Log.WithFields( + map[string]interface{}{ + common.LabelEventSource: es.Name, + common.LabelVersion: es.Version, + }).Info("validating event source") + return gwcommon.ValidateGatewayEventSource(es, ArgoEventsEventSourceVersion, parseEventSource, validateWebhook) } func validateWebhook(config interface{}) error { diff --git a/gateways/core/webhook/validate_test.go b/gateways/core/webhook/validate_test.go index 087ae8835a..e79c000bb4 100644 --- a/gateways/core/webhook/validate_test.go +++ b/gateways/core/webhook/validate_test.go @@ -18,47 +18,55 @@ package webhook import ( "context" - "github.com/smartystreets/goconvey/convey" + "fmt" + "io/ioutil" "testing" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/gateways" + gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" + "github.com/smartystreets/goconvey/convey" + corev1 "k8s.io/api/core/v1" ) -var ( - configKey = "testConfig" - configId = "1234" - configValue = ` -endpoint: "/bar" -port: "10000" -method: "POST" -` -) - -func TestValidateNatsEventSource(t *testing.T) { +func TestValidateEventSource(t *testing.T) { convey.Convey("Given a valid webhook event source spec, parse it and make sure no error occurs", t, func() { - ese := &WebhookEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: configValue, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) + ese := &WebhookEventSourceExecutor{ + Log: common.NewArgoEventsLogger(), + } + content, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", gwcommon.EventSourceDir, "webhook.yaml")) + convey.So(err, convey.ShouldBeNil) + + var cm *corev1.ConfigMap + err = yaml.Unmarshal(content, &cm) + convey.So(err, convey.ShouldBeNil) + convey.So(cm, convey.ShouldNotBeNil) + + err = common.CheckEventSourceVersion(cm) + convey.So(err, convey.ShouldBeNil) + + for key, value := range cm.Data { + valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ + Name: key, + Id: common.Hasher(key), + Data: value, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], + }) + convey.So(valid, convey.ShouldNotBeNil) + convey.So(valid.IsValid, convey.ShouldBeTrue) + } }) +} - convey.Convey("Given an invalid webhook event source spec, parse it and make sure error occurs", t, func() { - ese := &WebhookEventSourceExecutor{} - invalidConfig := ` -endpoint: "/bar" -port: "10000" -` - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: invalidConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) +func TestValidate(t *testing.T) { + convey.Convey("Given a webhook, validate it", t, func() { + w := &gwcommon.Webhook{ + Port: "12000", + Endpoint: "/", + Method: "POST", + } + err := validateWebhook(w) + convey.So(err, convey.ShouldBeNil) }) } diff --git a/gateways/event-source_test.go b/gateways/event-source_test.go index c84404bdcf..361e239f03 100644 --- a/gateways/event-source_test.go +++ b/gateways/event-source_test.go @@ -97,6 +97,9 @@ func TestEventSources(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "gateway-configmap", Namespace: "test-namespace", + Labels: map[string]string{ + common.LabelArgoEventsEventSourceVersion: "v0.10", + }, }, Data: map[string]string{ "event-source-1": ` @@ -113,9 +116,10 @@ testKey: testValue convey.So(eventSrcCtxMap, convey.ShouldNotBeNil) convey.So(len(eventSrcCtxMap), convey.ShouldEqual, 1) for _, data := range eventSrcCtxMap { - convey.So(data.Data.Config, convey.ShouldEqual, ` + convey.So(data.Source.Data, convey.ShouldEqual, ` testKey: testValue `) + convey.So(data.Source.Version, convey.ShouldEqual, "v0.10") } }) diff --git a/gateways/event-sources.go b/gateways/event-sources.go index 5129048efe..1842820287 100644 --- a/gateways/event-sources.go +++ b/gateways/event-sources.go @@ -54,8 +54,7 @@ func (gc *GatewayConfig) createInternalEventSources(cm *corev1.ConfigMap) (map[s grpc.WithInsecure(), grpc.WithTimeout(common.ServerConnTimeout*time.Second)) if err != nil { - gc.Log.WithError(err). - WithField("conn-state", conn.GetState().String()).Panic("failed to connect to gateway server") + gc.Log.WithError(err).Panic("failed to connect to gateway server") cancel() return nil, err } @@ -63,10 +62,11 @@ func (gc *GatewayConfig) createInternalEventSources(cm *corev1.ConfigMap) (map[s gc.Log.WithField("state", conn.GetState().String()).Info("state of the connection") configs[hashKey] = &EventSourceContext{ - Data: &EventSourceData{ - ID: hashKey, - Src: configKey, - Config: configValue, + Source: &EventSource{ + Id: hashKey, + Name: configKey, + Data: configValue, + Version: cm.Labels[common.LabelArgoEventsEventSourceVersion], }, Cancel: cancel, Ctx: ctx, @@ -132,7 +132,7 @@ func (gc *GatewayConfig) startEventSources(eventSources map[string]*EventSourceC // register the event source gc.registeredConfigs[key] = eventSource - log := gc.Log.WithField(common.LabelEventSource, eventSource.Data.Src) + log := gc.Log.WithField(common.LabelEventSource, eventSource.Source.Name) log.Info("activating new event source") @@ -142,19 +142,15 @@ func (gc *GatewayConfig) startEventSources(eventSources map[string]*EventSourceC gc.Log.Error("connection is not in ready state.") gc.StatusCh <- EventSourceStatus{ Phase: v1alpha1.NodePhaseError, - Id: eventSource.Data.ID, + Id: eventSource.Source.Id, Message: "connection_is_not_in_ready_state", - Name: eventSource.Data.Src, + Name: eventSource.Source.Name, } return } // validate event source - if valid, _ := eventSource.Client.ValidateEventSource(eventSource.Ctx, &EventSource{ - Data: eventSource.Data.Config, - Name: eventSource.Data.Src, - Id: eventSource.Data.ID, - }); !valid.IsValid { + if valid, _ := eventSource.Client.ValidateEventSource(eventSource.Ctx, eventSource.Source); !valid.IsValid { gc.Log.WithFields( map[string]interface{}{ "validation-failure": valid.Reason, @@ -165,9 +161,9 @@ func (gc *GatewayConfig) startEventSources(eventSources map[string]*EventSourceC } gc.StatusCh <- EventSourceStatus{ Phase: v1alpha1.NodePhaseError, - Id: eventSource.Data.ID, + Id: eventSource.Source.Id, Message: "event_source_is_not_valid", - Name: eventSource.Data.Src, + Name: eventSource.Source.Name, } return } @@ -178,23 +174,19 @@ func (gc *GatewayConfig) startEventSources(eventSources map[string]*EventSourceC gc.StatusCh <- EventSourceStatus{ Phase: v1alpha1.NodePhaseRunning, Message: "event_source_is_running", - Id: eventSource.Data.ID, - Name: eventSource.Data.Src, + Id: eventSource.Source.Id, + Name: eventSource.Source.Name, } // listen to events from gateway server - eventStream, err := eventSource.Client.StartEventSource(eventSource.Ctx, &EventSource{ - Name: eventSource.Data.Src, - Data: eventSource.Data.Config, - Id: eventSource.Data.ID, - }) + eventStream, err := eventSource.Client.StartEventSource(eventSource.Ctx, eventSource.Source) if err != nil { gc.Log.WithError(err).Error("error occurred while starting event source") gc.StatusCh <- EventSourceStatus{ Phase: v1alpha1.NodePhaseError, Message: "failed_to_receive_event_stream", - Name: eventSource.Data.Src, - Id: eventSource.Data.ID, + Name: eventSource.Source.Name, + Id: eventSource.Source.Id, } return } @@ -208,8 +200,8 @@ func (gc *GatewayConfig) startEventSources(eventSources map[string]*EventSourceC gc.StatusCh <- EventSourceStatus{ Phase: v1alpha1.NodePhaseCompleted, Message: "event_source_has_been_stopped", - Name: eventSource.Data.Src, - Id: eventSource.Data.ID, + Name: eventSource.Source.Name, + Id: eventSource.Source.Id, } return } @@ -218,8 +210,8 @@ func (gc *GatewayConfig) startEventSources(eventSources map[string]*EventSourceC gc.StatusCh <- EventSourceStatus{ Phase: v1alpha1.NodePhaseError, Message: "failed_to_receive_event_from_event_source_stream", - Name: eventSource.Data.Src, - Id: eventSource.Data.ID, + Name: eventSource.Source.Name, + Id: eventSource.Source.Id, } return } @@ -228,9 +220,9 @@ func (gc *GatewayConfig) startEventSources(eventSources map[string]*EventSourceC // escalate error through a K8s event labels := map[string]string{ common.LabelEventType: string(common.EscalationEventType), - common.LabelGatewayEventSourceName: eventSource.Data.Src, + common.LabelGatewayEventSourceName: eventSource.Source.Name, common.LabelGatewayName: gc.Name, - common.LabelGatewayEventSourceID: eventSource.Data.ID, + common.LabelGatewayEventSourceID: eventSource.Source.Id, common.LabelOperation: "dispatch_event_to_watchers", } if err := common.GenerateK8sEvent(gc.Clientset, fmt.Sprintf("failed to dispatch event to watchers"), common.EscalationEventType, "event dispatch failed", gc.Name, gc.Namespace, gc.controllerInstanceID, gateway.Kind, labels); err != nil { @@ -248,16 +240,16 @@ func (gc *GatewayConfig) stopEventSources(configs []string) { for _, configKey := range configs { eventSource := gc.registeredConfigs[configKey] delete(gc.registeredConfigs, configKey) - gc.Log.WithEventSource(eventSource.Data.Src).Info("removing the event source") + gc.Log.WithField(common.LabelEventSource, eventSource.Source.Name).Info("removing the event source") gc.StatusCh <- EventSourceStatus{ Phase: v1alpha1.NodePhaseRemove, - Id: eventSource.Data.ID, + Id: eventSource.Source.Id, Message: "event_source_is_removed", - Name: eventSource.Data.Src, + Name: eventSource.Source.Name, } eventSource.Cancel() if err := eventSource.Conn.Close(); err != nil { - gc.Log.WithEventSource(eventSource.Data.Src).WithError(err).Error("failed to close client connection") + gc.Log.WithField(common.LabelEventSource, eventSource.Source.Name).WithError(err).Error("failed to close client connection") } } } diff --git a/gateways/eventing.pb.go b/gateways/eventing.pb.go index bf1f7f02ae..b48e844933 100644 --- a/gateways/eventing.pb.go +++ b/gateways/eventing.pb.go @@ -30,7 +30,9 @@ type EventSource struct { // The event source name. Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // The event source configuration value. - Data string `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` + Data string `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` + // Version of the event source + Version string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -82,6 +84,13 @@ func (m *EventSource) GetData() string { return "" } +func (m *EventSource) GetVersion() string { + if m != nil { + return m.Version + } + return "" +} + //* // Represents an event type Event struct { @@ -193,21 +202,22 @@ func init() { func init() { proto.RegisterFile("gateways/eventing.proto", fileDescriptor_c25325013aefc28a) } var fileDescriptor_c25325013aefc28a = []byte{ - // 224 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x90, 0xb1, 0x4a, 0xc7, 0x30, - 0x10, 0x87, 0x49, 0xd5, 0xb6, 0x9e, 0xa2, 0x25, 0xa2, 0x86, 0x4e, 0xd2, 0xc9, 0xa9, 0x8a, 0xe2, - 0xe6, 0x68, 0xc1, 0xb9, 0x05, 0xf7, 0xd3, 0x84, 0x12, 0xa8, 0x49, 0x49, 0xa3, 0xd2, 0xd7, 0xf0, - 0x89, 0xa5, 0x67, 0xa3, 0xa1, 0xd3, 0x7f, 0xbb, 0xfb, 0x8e, 0xfb, 0x72, 0xbf, 0xc0, 0x65, 0x8f, - 0x5e, 0x7d, 0xe1, 0x3c, 0xdd, 0xa8, 0x4f, 0x65, 0xbc, 0x36, 0x7d, 0x3d, 0x3a, 0xeb, 0x2d, 0xcf, - 0xc3, 0xa0, 0x6a, 0xe0, 0xa8, 0x59, 0x66, 0x9d, 0xfd, 0x70, 0x6f, 0x8a, 0x9f, 0x40, 0xa2, 0xa5, - 0x60, 0x57, 0xec, 0xfa, 0xb0, 0x4d, 0xb4, 0xe4, 0x1c, 0xf6, 0x0d, 0xbe, 0x2b, 0x91, 0x10, 0xa1, - 0x7a, 0x61, 0x12, 0x3d, 0x8a, 0xbd, 0x5f, 0xb6, 0xd4, 0xd5, 0x03, 0x1c, 0x90, 0xe6, 0x6f, 0x81, - 0x45, 0x0b, 0x02, 0xb2, 0x11, 0xe7, 0xc1, 0xa2, 0x24, 0xcf, 0x71, 0x1b, 0xda, 0xea, 0x09, 0x8a, - 0x17, 0x1c, 0xb4, 0x8c, 0x4f, 0x10, 0x90, 0xe9, 0x89, 0x28, 0x49, 0xf2, 0x36, 0xb4, 0xfc, 0x02, - 0x52, 0xa7, 0x70, 0xb2, 0x66, 0x3d, 0x67, 0xed, 0xee, 0xbe, 0x19, 0xe4, 0xcd, 0x1a, 0x90, 0x3f, - 0x42, 0xd1, 0x79, 0x74, 0x3e, 0x56, 0x9e, 0xd7, 0x21, 0x6f, 0x1d, 0xe1, 0xf2, 0x74, 0x83, 0x6f, - 0x19, 0x7f, 0x86, 0x33, 0x7a, 0x0b, 0xbd, 0xda, 0x41, 0x50, 0xfe, 0xe3, 0x6d, 0x8c, 0xd7, 0x94, - 0x7e, 0xfa, 0xfe, 0x27, 0x00, 0x00, 0xff, 0xff, 0x5d, 0x9d, 0xb2, 0xf4, 0x84, 0x01, 0x00, 0x00, + // 239 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0xc1, 0x4a, 0x03, 0x31, + 0x10, 0x86, 0xc9, 0x5a, 0xbb, 0xeb, 0x28, 0x5a, 0x46, 0xd4, 0xd0, 0x93, 0xec, 0xc9, 0xd3, 0x2a, + 0x8a, 0x37, 0x8f, 0x16, 0x3c, 0x6f, 0xc1, 0xab, 0x8c, 0x66, 0x28, 0x81, 0x9a, 0x94, 0x6c, 0xac, + 0xf4, 0x35, 0x7c, 0x62, 0xd9, 0x71, 0xa3, 0x61, 0x4f, 0xde, 0xe6, 0xff, 0x06, 0xbe, 0x99, 0x49, + 0xe0, 0x62, 0x45, 0x91, 0x3f, 0x69, 0xd7, 0x5d, 0xf3, 0x96, 0x5d, 0xb4, 0x6e, 0xd5, 0x6c, 0x82, + 0x8f, 0x1e, 0xab, 0xd4, 0xa8, 0x5f, 0xe0, 0x70, 0xd1, 0xf7, 0x96, 0xfe, 0x23, 0xbc, 0x31, 0x1e, + 0x43, 0x61, 0x8d, 0x56, 0x97, 0xea, 0xea, 0xa0, 0x2d, 0xac, 0x41, 0x84, 0x89, 0xa3, 0x77, 0xd6, + 0x85, 0x10, 0xa9, 0x7b, 0x66, 0x28, 0x92, 0xde, 0xfb, 0x61, 0x7d, 0x8d, 0x1a, 0xca, 0x2d, 0x87, + 0xce, 0x7a, 0xa7, 0x27, 0x82, 0x53, 0xac, 0xef, 0x61, 0x5f, 0x06, 0xfc, 0xaa, 0x54, 0xa6, 0xd2, + 0x50, 0x6e, 0x68, 0xb7, 0xf6, 0x64, 0x64, 0xc2, 0x51, 0x9b, 0x62, 0xfd, 0x08, 0xb3, 0x67, 0x5a, + 0x5b, 0x93, 0x2f, 0xa7, 0xa1, 0xb4, 0x9d, 0x50, 0x91, 0x54, 0x6d, 0x8a, 0x78, 0x0e, 0xd3, 0xc0, + 0xd4, 0x79, 0x37, 0x2c, 0x3a, 0xa4, 0xdb, 0x2f, 0x05, 0xd5, 0x62, 0x38, 0x1d, 0x1f, 0x60, 0xb6, + 0x8c, 0x14, 0x62, 0xae, 0x3c, 0x6b, 0xd2, 0x4b, 0x34, 0x19, 0x9e, 0x9f, 0x8c, 0xf0, 0x8d, 0xc2, + 0x27, 0x38, 0x95, 0x59, 0x14, 0xf9, 0x1f, 0x82, 0xf9, 0x1f, 0x1e, 0x9f, 0xf1, 0x3a, 0x95, 0x3f, + 0xb8, 0xfb, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x08, 0x55, 0x59, 0x7f, 0x9e, 0x01, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/gateways/eventing.proto b/gateways/eventing.proto index fe2bd52636..d45e592d0e 100644 --- a/gateways/eventing.proto +++ b/gateways/eventing.proto @@ -26,6 +26,8 @@ message EventSource { string name = 2; // The event source configuration value. string data = 3; + // Version of the event source + string version = 4; } /** diff --git a/gateways/gateway.go b/gateways/gateway.go index 452b457c2f..e29c6d9b3e 100644 --- a/gateways/gateway.go +++ b/gateways/gateway.go @@ -19,6 +19,7 @@ package gateways import ( "fmt" "github.com/argoproj/argo-events/common" + "github.com/sirupsen/logrus" "google.golang.org/grpc" "net" "os" @@ -54,11 +55,11 @@ func Recover(eventSource string) { } // HandleEventsFromEventSource handles events from the event source. -func HandleEventsFromEventSource(name string, eventStream Eventing_StartEventSourceServer, dataCh chan []byte, errorCh chan error, doneCh chan struct{}, log *common.ArgoEventsLogger) error { +func HandleEventsFromEventSource(name string, eventStream Eventing_StartEventSourceServer, dataCh chan []byte, errorCh chan error, doneCh chan struct{}, log *logrus.Logger) error { for { select { case data := <-dataCh: - log.WithEventSource(name).Info("new event received, dispatching to gateway client") + log.WithField(common.LabelEventSource, name).Info("new event received, dispatching to gateway client") err := eventStream.Send(&Event{ Name: name, Payload: data, @@ -68,11 +69,11 @@ func HandleEventsFromEventSource(name string, eventStream Eventing_StartEventSou } case err := <-errorCh: - log.WithEventSource(name).WithError(err).Error("error occurred while getting event from event source") + log.WithField(common.LabelEventSource, name).WithError(err).Error("error occurred while getting event from event source") return err case <-eventStream.Context().Done(): - log.WithEventSource(name).Info("connection is closed by client") + log.WithField(common.LabelEventSource, name).Info("connection is closed by client") doneCh <- struct{}{} return nil } diff --git a/gateways/state.go b/gateways/state.go index 1f60a0eb61..c292f89cb5 100644 --- a/gateways/state.go +++ b/gateways/state.go @@ -106,7 +106,10 @@ func (gc *GatewayConfig) initializeNode(nodeID string, nodeName string, messages // UpdateGatewayResourceState updates gateway resource nodes state func (gc *GatewayConfig) UpdateGatewayResourceState(status *EventSourceStatus) { - log := gc.Log.WithEventSource(status.Name) + log := gc.Log + if status.Phase != v1alpha1.NodePhaseResourceUpdate { + log = log.WithField(common.LabelEventSource, status.Name).Logger + } log.Info("received a gateway state update notification") diff --git a/gateways/transformer.go b/gateways/transformer.go index 016e18dbb5..1283fdbe52 100644 --- a/gateways/transformer.go +++ b/gateways/transformer.go @@ -20,6 +20,7 @@ import ( "bytes" "encoding/json" "fmt" + "github.com/argoproj/argo-events/pkg/apis/gateway/v1alpha1" "net/http" "time" @@ -71,7 +72,7 @@ func (gc *GatewayConfig) transformEvent(gatewayEvent *Event) (*apicommon.Event, // Generate an event id eventId := suuid.NewV1() - gc.Log.WithEventSource(gatewayEvent.Name).Info("converting gateway event into cloudevents specification compliant event") + gc.Log.WithField(common.LabelEventSource, gatewayEvent.Name).Info("converting gateway event into cloudevents specification compliant event") // Create an CloudEvent ce := &apicommon.Event{ @@ -81,7 +82,7 @@ func (gc *GatewayConfig) transformEvent(gatewayEvent *Event) (*apicommon.Event, ContentType: "application/json", EventTime: metav1.MicroTime{Time: time.Now().UTC()}, EventType: gc.gw.Spec.Type, - EventTypeVersion: gc.gw.Spec.EventVersion, + EventTypeVersion: v1alpha1.ArgoEventsGatewayVersion, Source: &apicommon.URI{ Host: common.DefaultEventSourceName(gc.gw.Name, gatewayEvent.Name), }, @@ -89,25 +90,25 @@ func (gc *GatewayConfig) transformEvent(gatewayEvent *Event) (*apicommon.Event, Payload: gatewayEvent.Payload, } - gc.Log.WithEventSource(gatewayEvent.Name).Info("event has been transformed into cloud event") + gc.Log.WithField(common.LabelGatewayName, gatewayEvent.Name).Info("event has been transformed into cloud event") return ce, nil } // dispatchEventOverHttp dispatches event to watchers over http. func (gc *GatewayConfig) dispatchEventOverHttp(source string, eventPayload []byte) error { - gc.Log.WithEventSource(source).Info("dispatching event to watchers") + gc.Log.WithField(common.LabelEventSource, source).Info("dispatching event to watchers") completeSuccess := true for _, sensor := range gc.gw.Spec.Watchers.Sensors { if err := gc.postCloudEventToWatcher(common.DefaultServiceName(sensor.Name), gc.gw.Spec.EventProtocol.Http.Port, common.SensorServiceEndpoint, eventPayload); err != nil { - gc.Log.WithEventSource(source).WithSensorName(sensor.Name).Warn("failed to dispatch event to sensor watcher over http. communication error") + gc.Log.WithField(common.LabelSensorName, sensor.Name).WithError(err).Warn("failed to dispatch event to sensor watcher over http. communication error") completeSuccess = false } } for _, gateway := range gc.gw.Spec.Watchers.Gateways { if err := gc.postCloudEventToWatcher(common.DefaultServiceName(gateway.Name), gateway.Port, gateway.Endpoint, eventPayload); err != nil { - gc.Log.WithEventSource(source).WithGatewayName(gateway.Name).WithError(err).Warn("failed to dispatch event to gateway watcher over http. communication error") + gc.Log.WithField(common.LabelGatewayName, gateway.Name).WithError(err).Warn("failed to dispatch event to gateway watcher over http. communication error") completeSuccess = false } } @@ -133,11 +134,11 @@ func (gc *GatewayConfig) dispatchEventOverNats(source string, eventPayload []byt } if err != nil { - gc.Log.WithEventSource(source).WithError(err).Error("failed to publish event") + gc.Log.WithField(common.LabelEventSource, source).WithError(err).Error("failed to publish event") return err } - gc.Log.WithEventSource(source).Info("event published successfully") + gc.Log.WithField(common.LabelEventSource, source).Info("event published successfully") return nil } diff --git a/gateways/watcher.go b/gateways/watcher.go index 6164d0dd7c..af6da88261 100644 --- a/gateways/watcher.go +++ b/gateways/watcher.go @@ -19,6 +19,7 @@ package gateways import ( "context" "fmt" + "github.com/argoproj/argo-events/common" "github.com/argoproj/argo-events/pkg/apis/gateway/v1alpha1" corev1 "k8s.io/api/core/v1" @@ -39,19 +40,27 @@ func (gc *GatewayConfig) WatchGatewayEventSources(ctx context.Context) (cache.Co cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { if newCm, ok := obj.(*corev1.ConfigMap); ok { - gc.Log.WithField("name", newCm.Name).Info("detected configmap addition") - err := gc.manageEventSources(newCm) - if err != nil { - gc.Log.WithError(err).Error("add config failed") + if err := common.CheckEventSourceVersion(newCm); err != nil { + gc.Log.WithField("name", newCm.Name).Error(err) + } else { + gc.Log.WithField("name", newCm.Name).Info("detected configmap addition") + err := gc.manageEventSources(newCm) + if err != nil { + gc.Log.WithError(err).Error("add config failed") + } } } }, UpdateFunc: func(old, new interface{}) { if cm, ok := new.(*corev1.ConfigMap); ok { - gc.Log.Info("detected ConfigMap update. Updating the controller run config.") - err := gc.manageEventSources(cm) - if err != nil { - gc.Log.WithError(err).Error("update config failed") + if err := common.CheckEventSourceVersion(cm); err != nil { + gc.Log.WithField("name", cm.Name).Error(err) + } else { + gc.Log.Info("detected EventSource update. Updating the controller run config.") + err := gc.manageEventSources(cm) + if err != nil { + gc.Log.WithError(err).Error("update config failed") + } } } }, diff --git a/hack/e2e/cleanup-e2e.sh b/hack/e2e/cleanup-e2e.sh deleted file mode 100755 index e990bdbbbc..0000000000 --- a/hack/e2e/cleanup-e2e.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -set -e - -kubectl delete ns -l argo-events-e2e diff --git a/hack/e2e/kind-run-e2e.sh b/hack/e2e/kind-run-e2e.sh index 5b1d41b513..583feae0ad 100755 --- a/hack/e2e/kind-run-e2e.sh +++ b/hack/e2e/kind-run-e2e.sh @@ -6,25 +6,35 @@ PROJECT_ROOT=$(cd $(dirname ${BASH_SOURCE})/../..; pwd) KUBERNETES_VERSION=${KUBERNETES_VERSION:-kindest/node:v1.13.4} CLUSTER_NAME=${CLUSTER_NAME:-kind-argo-events} IMAGE_PREFIX=${IMAGE_PREFIX:-argoproj/} -IMAGE_TAG=${IMAGE_TAG:-latest} +IMAGE_TAG=${IMAGE_TAG:-v0.10-test} kind create cluster --name $CLUSTER_NAME --image $KUBERNETES_VERSION export KUBECONFIG="$(kind get kubeconfig-path --name=$CLUSTER_NAME)" kubectl cluster-info +kind load docker-image --name $CLUSTER_NAME ${IMAGE_PREFIX}sensor-controller:${IMAGE_TAG} ${IMAGE_PREFIX}gateway-controller:${IMAGE_TAG} ${IMAGE_PREFIX}webhook-gateway:${IMAGE_TAG} ${IMAGE_PREFIX}gateway-client:${IMAGE_TAG} + +PROJECT_ROOT=$(cd $(dirname ${BASH_SOURCE})/../..; pwd) -function cleanup { - if [[ -z "$KEEP_CLUSTER" ]]; then - echo "* Cleaning up the e2e cluter..." - kind delete cluster --name $CLUSTER_NAME - else - echo "* Skip e2e cluster cleanup for $CLUSTER_NAME." - fi -} -trap cleanup EXIT +echo "* Set up e2e test" -kind load docker-image --name $CLUSTER_NAME ${IMAGE_PREFIX}sensor-controller:${IMAGE_TAG} ${IMAGE_PREFIX}gateway-controller:${IMAGE_TAG} ${IMAGE_PREFIX}webhook-gateway:${IMAGE_TAG} ${IMAGE_PREFIX}gateway-client:${IMAGE_TAG} +kubectl create namespace argo-events +kubectl apply -n argo-events -f $PROJECT_ROOT/hack/k8s/manifests/argo-events-sa.yaml +kubectl apply -n argo-events -f $PROJECT_ROOT/hack/k8s/manifests/argo-events-cluster-roles.yaml +kubectl apply -n argo-events -f $PROJECT_ROOT/hack/k8s/manifests/sensor-crd.yaml +kubectl apply -n argo-events -f $PROJECT_ROOT/hack/k8s/manifests/gateway-crd.yaml +kubectl apply -n argo-events -f $PROJECT_ROOT/hack/k8s/manifests/sensor-controller-configmap.yaml +kubectl apply -n argo-events -f $PROJECT_ROOT/hack/k8s/manifests/gateway-controller-configmap.yaml + +# changes are only made for controller images +kubectl apply -n argo-events -f $PROJECT_ROOT/hack/e2e/manifests/sensor-controller-deployment.yaml +kubectl apply -n argo-events -f $PROJECT_ROOT/hack/e2e/manifests/gateway-controller-deployment.yaml + + +# wait for controllers to get up and running +sleep 10 -# Avoid too early access -sleep 1 +echo "* Run e2e tests." +go test -v ./test/e2e/... -$PROJECT_ROOT/hack/e2e/run-e2e.sh +# delete the cluster +kind delete cluster --name $CLUSTER_NAME diff --git a/hack/e2e/manifests/argo-events-cluster-roles.yaml b/hack/e2e/manifests/argo-events-cluster-roles.yaml deleted file mode 100644 index 9d728eec57..0000000000 --- a/hack/e2e/manifests/argo-events-cluster-roles.yaml +++ /dev/null @@ -1,94 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: argo-events-binding - namespace: "__E2E_ID__" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: argo-events-role -subjects: -- kind: ServiceAccount - name: argo-events-sa - namespace: "__E2E_ID__" ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: argo-events-role - namespace: "__E2E_ID__" -rules: - - apiGroups: - - apiextensions.k8s.io - - apiextensions.k8s.io/v1beta1 - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch - resources: - - customresourcedefinitions - - apiGroups: - - argoproj.io - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch - resources: - - gateways - - gateways/finalizers - - sensors - - sensors/finalizers - - apiGroups: - - "" - resources: - - pods - - pods/exec - - configmaps - - secrets - - services - - events - - persistentvolumeclaims - verbs: - - create - - get - - list - - watch - - update - - patch - - delete - - apiGroups: - - "batch" - resources: - - jobs - verbs: - - create - - get - - list - - watch - - update - - patch - - delete - - apiGroups: - - "apps/v1" - - "apps/v1beta2" - - "apps/v1beta1" - resources: - - deployments - verbs: - - create - - get - - list - - watch - - update - - patch - - delete diff --git a/hack/e2e/manifests/argo-events-sa.yaml b/hack/e2e/manifests/argo-events-sa.yaml deleted file mode 100644 index c3c7bd3013..0000000000 --- a/hack/e2e/manifests/argo-events-sa.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: argo-events-sa - namespace: "__E2E_ID__" diff --git a/hack/e2e/manifests/gateway-controller-configmap.yaml b/hack/e2e/manifests/gateway-controller-configmap.yaml deleted file mode 100644 index 75227674f7..0000000000 --- a/hack/e2e/manifests/gateway-controller-configmap.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: gateway-controller-configmap - namespace: "__E2E_ID__" -data: - config: | - instanceID: "__E2E_ID__" - namespace: "" diff --git a/hack/e2e/manifests/gateway-controller-deployment.yaml b/hack/e2e/manifests/gateway-controller-deployment.yaml old mode 100644 new mode 100755 index d855fcdd83..c7cdcf69a4 --- a/hack/e2e/manifests/gateway-controller-deployment.yaml +++ b/hack/e2e/manifests/gateway-controller-deployment.yaml @@ -1,12 +1,13 @@ -apiVersion: apps/v1beta1 +# The gateway-controller listens for changes on the gateway CRD and creates gateway +apiVersion: apps/v1 kind: Deployment metadata: name: gateway-controller - namespace: "__E2E_ID__" - labels: - gateways.argoproj.io/sensor-controller-instanceid: "__E2E_ID__" spec: replicas: 1 + selector: + matchLabels: + app: gateway-controller template: metadata: labels: @@ -15,7 +16,7 @@ spec: serviceAccountName: argo-events-sa containers: - name: gateway-controller - image: argoproj/gateway-controller + image: argoproj/gateway-controller:v0.10-test imagePullPolicy: Always env: - name: GATEWAY_NAMESPACE diff --git a/hack/e2e/manifests/sensor-controller-configmap.yaml b/hack/e2e/manifests/sensor-controller-configmap.yaml deleted file mode 100644 index e86e6b811b..0000000000 --- a/hack/e2e/manifests/sensor-controller-configmap.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: sensor-controller-configmap - namespace: "__E2E_ID__" -data: - config: | - instanceID: "__E2E_ID__" - namespace: "" diff --git a/hack/e2e/manifests/sensor-controller-deployment.yaml b/hack/e2e/manifests/sensor-controller-deployment.yaml old mode 100644 new mode 100755 index dce7fb8510..e7f1f73941 --- a/hack/e2e/manifests/sensor-controller-deployment.yaml +++ b/hack/e2e/manifests/sensor-controller-deployment.yaml @@ -1,12 +1,13 @@ -apiVersion: apps/v1beta1 +# The sensor-controller listens for changes on the sensor CRD and creates sensor executor jobs +apiVersion: apps/v1 kind: Deployment metadata: name: sensor-controller - namespace: "__E2E_ID__" - labels: - sensors.argoproj.io/sensor-controller-instanceid: "__E2E_ID__" spec: replicas: 1 + selector: + matchLabels: + app: sensor-controller template: metadata: labels: @@ -15,7 +16,7 @@ spec: serviceAccountName: argo-events-sa containers: - name: sensor-controller - image: argoproj/sensor-controller + image: argoproj/sensor-controller:v0.10-test imagePullPolicy: Always env: - name: SENSOR_NAMESPACE diff --git a/hack/e2e/run-e2e.sh b/hack/e2e/run-e2e.sh deleted file mode 100755 index 018f686bf7..0000000000 --- a/hack/e2e/run-e2e.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -e - -PROJECT_ROOT=$(cd $(dirname ${BASH_SOURCE})/../..; pwd) - -export E2E_ID=${E2E_ID:-argo-events-e2e-$(date +%s)} - -$PROJECT_ROOT/hack/e2e/setup-e2e.sh - -function cleanup { - if [[ -z "$KEEP_NAMESPACE" ]]; then - echo "* Cleaning up the e2e environment..." - kubectl delete ns $E2E_ID - else - echo "* Skip e2e environment cleanup for $E2E_ID." - fi -} -trap cleanup EXIT - -echo "* Run e2e tests." -go test -v ./test/e2e/... diff --git a/hack/e2e/setup-e2e.sh b/hack/e2e/setup-e2e.sh index 7a27289ef5..313c912dc3 100755 --- a/hack/e2e/setup-e2e.sh +++ b/hack/e2e/setup-e2e.sh @@ -23,10 +23,10 @@ metadata: argo-events-e2e: "$E2E_ID" EOS -# ls $PROJECT_ROOT/hack/e2e/manifests/* | xargs -I {} sed -e "s|__E2E_ID__|$E2E_ID|g" {} | kubectl apply -f - +# ls $PROJECT_ROOT/hack/e2e/manifests/* | xargs -I {} sed -e "s|E2E_ID|$E2E_ID|g" {} | kubectl apply -f - manifests=$(ls $PROJECT_ROOT/hack/e2e/manifests/*) for m in $manifests; do - sed -e "s|__E2E_ID__|$E2E_ID|g" $m | kubectl apply -f - + sed -e "s|E2E_ID|$E2E_ID|g" $m | kubectl apply -f - done # wait for controllers up diff --git a/hack/k8s/manifests/gateway-controller-deployment.yaml b/hack/k8s/manifests/gateway-controller-deployment.yaml index 8e269085f5..0b4f37231c 100644 --- a/hack/k8s/manifests/gateway-controller-deployment.yaml +++ b/hack/k8s/manifests/gateway-controller-deployment.yaml @@ -1,10 +1,13 @@ # The gateway-controller listens for changes on the gateway CRD and creates gateway -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: gateway-controller spec: replicas: 1 + selector: + matchLabels: + app: gateway-controller template: metadata: labels: diff --git a/hack/k8s/manifests/sensor-controller-deployment.yaml b/hack/k8s/manifests/sensor-controller-deployment.yaml index 343eec737d..43886f61e6 100644 --- a/hack/k8s/manifests/sensor-controller-deployment.yaml +++ b/hack/k8s/manifests/sensor-controller-deployment.yaml @@ -1,10 +1,13 @@ # The sensor-controller listens for changes on the sensor CRD and creates sensor executor jobs -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: sensor-controller spec: replicas: 1 + selector: + matchLabels: + app: sensor-controller template: metadata: labels: diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000000..b403edf95f --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,42 @@ +site_name: Argo Events - The Event-Based Dependency Manager for Kubernetes +repo_url: https://github.com/argoproj/argo-events +strict: true +theme: + name: material + palette: + primary: teal + font: + text: 'Work Sans' + logo: 'assets/logo.png' +google_analytics: +- 'UA-105170809-2' +- 'auto' +markdown_extensions: +- codehilite +- admonition +- toc: + permalink: true +nav: + - Overview: index.md + - gateway.md + - sensor.md + - trigger.md + - communication.md + - controllers.md + - Setup: + - gateways/artifact.md + - gateways/aws-sns.md + - gateways/aws-sqs.md + - gateways/calendar.md + - gateways/file.md + - gateways/gcp-pubsub.md + - gateways/github.md + - gateways/gitlab.md + - gateways/resource.md + - gateways/slack.md + - gateways/storage-grid.md + - gateways/streams.md + - gateways/webhook.md + - Releases ⧉: https://github.com/argoproj/argo-events/releases + - Roadmap ⧉: https://github.com/argoproj/argo-events/milestones + - Blog ⧉: https://blog.argoproj.io/ diff --git a/pkg/apis/gateway/v1alpha1/openapi_generated.go b/pkg/apis/gateway/v1alpha1/openapi_generated.go index 203d17e701..b93421c4f8 100644 --- a/pkg/apis/gateway/v1alpha1/openapi_generated.go +++ b/pkg/apis/gateway/v1alpha1/openapi_generated.go @@ -179,9 +179,9 @@ func schema_pkg_apis_gateway_v1alpha1_GatewaySpec(ref common.ReferenceCallback) Ref: ref("k8s.io/api/core/v1.PodTemplateSpec"), }, }, - "configMap": { + "eventSource": { SchemaProps: spec.SchemaProps{ - Description: "ConfigMap is name of the configmap for gateway. This configmap contains event sources.", + Description: "EventSource is name of the configmap that stores event source configurations for the gateway", Type: []string{"string"}, Format: "", }, @@ -193,13 +193,6 @@ func schema_pkg_apis_gateway_v1alpha1_GatewaySpec(ref common.ReferenceCallback) Format: "", }, }, - "eventVersion": { - SchemaProps: spec.SchemaProps{ - Description: "Version is used for marking event version", - Type: []string{"string"}, - Format: "", - }, - }, "service": { SchemaProps: spec.SchemaProps{ Description: "Service is the specifications of the service to expose the gateway Refer https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.11/#service-v1-core", @@ -226,7 +219,7 @@ func schema_pkg_apis_gateway_v1alpha1_GatewaySpec(ref common.ReferenceCallback) }, }, }, - Required: []string{"template", "type", "eventVersion", "processorPort", "eventProtocol"}, + Required: []string{"template", "type", "processorPort", "eventProtocol"}, }, }, Dependencies: []string{ diff --git a/pkg/apis/gateway/v1alpha1/types.go b/pkg/apis/gateway/v1alpha1/types.go index 66b81ad7a2..201afb8377 100644 --- a/pkg/apis/gateway/v1alpha1/types.go +++ b/pkg/apis/gateway/v1alpha1/types.go @@ -22,6 +22,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +// Gateway version +const ArgoEventsGatewayVersion = "v0.10" + // NodePhase is the label for the condition of a node. type NodePhase string @@ -60,30 +63,27 @@ type GatewaySpec struct { // Refer https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.11/#pod-v1-core Template *corev1.PodTemplateSpec `json:"template" protobuf:"bytes,1,opt,name=template"` - // ConfigMap is name of the configmap for gateway. This configmap contains event sources. - ConfigMap string `json:"configMap,omitempty" protobuf:"bytes,2,opt,name=configmap"` + // EventSource is name of the configmap that stores event source configurations for the gateway + EventSource string `json:"eventSource,omitempty" protobuf:"bytes,2,opt,name=eventSource"` // Type is the type of gateway. Used as metadata. Type string `json:"type" protobuf:"bytes,3,opt,name=type"` - // Version is used for marking event version - EventVersion string `json:"eventVersion" protobuf:"bytes,4,opt,name=eventVersion"` - // Service is the specifications of the service to expose the gateway // Refer https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.11/#service-v1-core - Service *common.ServiceTemplateSpec `json:"service,omitempty" protobuf:"bytes,5,opt,name=service"` + Service *common.ServiceTemplateSpec `json:"service,omitempty" protobuf:"bytes,4,opt,name=service"` // Watchers are components which are interested listening to notifications from this gateway // These only need to be specified when gateway dispatch mechanism is through HTTP POST notifications. // In future, support for NATS, KAFKA will be added as a means to dispatch notifications in which case // specifying watchers would be unnecessary. - Watchers *NotificationWatchers `json:"watchers,omitempty" protobuf:"bytes,6,opt,name=watchers"` + Watchers *NotificationWatchers `json:"watchers,omitempty" protobuf:"bytes,5,opt,name=watchers"` // Port on which the gateway event source processor is running on. - ProcessorPort string `json:"processorPort" protobuf:"bytes,7,opt,name=processorPort"` + ProcessorPort string `json:"processorPort" protobuf:"bytes,6,opt,name=processorPort"` // EventProtocol is the underlying protocol used to send events from gateway to watchers(components interested in listening to event from this gateway) - EventProtocol *common.EventProtocol `json:"eventProtocol" protobuf:"bytes,8,opt,name=eventProtocol"` + EventProtocol *common.EventProtocol `json:"eventProtocol" protobuf:"bytes,7,opt,name=eventProtocol"` } // GatewayStatus contains information about the status of a gateway. diff --git a/pkg/apis/sensor/v1alpha1/openapi_generated.go b/pkg/apis/sensor/v1alpha1/openapi_generated.go index 34a84732ed..796ef86c4a 100644 --- a/pkg/apis/sensor/v1alpha1/openapi_generated.go +++ b/pkg/apis/sensor/v1alpha1/openapi_generated.go @@ -22,8 +22,8 @@ limitations under the License. package v1alpha1 import ( - "github.com/go-openapi/spec" - "k8s.io/kube-openapi/pkg/common" + spec "github.com/go-openapi/spec" + common "k8s.io/kube-openapi/pkg/common" ) func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { diff --git a/pkg/apis/sensor/v1alpha1/types.go b/pkg/apis/sensor/v1alpha1/types.go index 8068d44b4b..313e716f65 100644 --- a/pkg/apis/sensor/v1alpha1/types.go +++ b/pkg/apis/sensor/v1alpha1/types.go @@ -28,6 +28,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +const ArgoEventsSensorVersion = "v0.10" + // NotificationType represent a type of notifications that are handled by a sensor type NotificationType string diff --git a/pkg/apis/sensor/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/sensor/v1alpha1/zz_generated.deepcopy.go index c28e6095d0..4b473206b9 100644 --- a/pkg/apis/sensor/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/sensor/v1alpha1/zz_generated.deepcopy.go @@ -20,10 +20,10 @@ limitations under the License. package v1alpha1 import ( - "github.com/argoproj/argo-events/pkg/apis/common" - "k8s.io/api/core/v1" + common "github.com/argoproj/argo-events/pkg/apis/common" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" + runtime "k8s.io/apimachinery/pkg/runtime" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. diff --git a/sensors/config.go b/sensors/config.go index 8224d0ed95..91069ab2a5 100644 --- a/sensors/config.go +++ b/sensors/config.go @@ -17,6 +17,7 @@ limitations under the License. package sensors import ( + "github.com/sirupsen/logrus" "net/http" "github.com/nats-io/go-nats" @@ -46,7 +47,7 @@ type sensorExecutionCtx struct { // http server which exposes the sensor to gateway/s server *http.Server // logger for the sensor - log *common.ArgoEventsLogger + log *logrus.Logger // queue is internal queue to manage incoming events queue chan *updateNotification // controllerInstanceID is the instance ID of sensor controller processing this sensor @@ -83,7 +84,7 @@ func NewSensorExecutionCtx(sensorClient clientset.Interface, kubeClient kubernet clientPool: clientPool, discoveryClient: discoveryClient, sensor: sensor, - log: common.NewArgoEventsLogger().WithSensorName(sensor.Name), + log: common.NewArgoEventsLogger().WithField(common.LabelSensorName, sensor.Name).Logger, queue: make(chan *updateNotification), controllerInstanceID: controllerInstanceID, } diff --git a/sensors/event-handler.go b/sensors/event-handler.go index 48f7f1e8a1..d5671f8c14 100644 --- a/sensors/event-handler.go +++ b/sensors/event-handler.go @@ -65,7 +65,7 @@ func (sec *sensorExecutionCtx) processUpdateNotification(ew *updateNotification) switch ew.notificationType { case v1alpha1.EventNotification: - log := sec.log.WithEventSource(ew.event.Context.Source.Host) + log := sec.log.WithField(common.LabelEventSource, ew.event.Context.Source.Host) log.Info("received event notification") // apply filters if any. diff --git a/sensors/http-events-handler.go b/sensors/http-events-handler.go index 42603fd45c..93b7f582f5 100644 --- a/sensors/http-events-handler.go +++ b/sensors/http-events-handler.go @@ -33,7 +33,7 @@ func (sec *sensorExecutionCtx) HttpEventProtocol() { // add a handler to handle incoming events http.HandleFunc("/", sec.httpEventHandler) - sec.log.WithPort(sec.sensor.Spec.EventProtocol.Http.Port).Info("sensor started listening") + sec.log.WithField(common.LabelPort, sec.sensor.Spec.EventProtocol.Http.Port).Info("sensor started listening") if err := sec.server.ListenAndServe(); err != nil { sec.log.WithError(err).Error("sensor server stopped") // escalate error @@ -71,12 +71,12 @@ func (sec *sensorExecutionCtx) httpEventHandler(w http.ResponseWriter, r *http.R // validate whether the event is from gateway that this sensor is watching and send event over internal queue if valid if sec.sendEventToInternalQueue(event, w) { response = "message successfully sent over internal queue" - sec.log.WithEventSource(event.Context.Source.Host).Info(response) + sec.log.WithField(common.LabelEventSource, event.Context.Source.Host).Info(response) common.SendSuccessResponse(w, response) return } response = "event is from unknown source" - sec.log.WithEventSource(event.Context.Source.Host).Warn(response) + sec.log.WithField(common.LabelEventSource, event.Context.Source.Host).Warn(response) common.SendErrorResponse(w, response) } diff --git a/sensors/nats-events-handler.go b/sensors/nats-events-handler.go index 6321fe9870..51fbdd27d7 100644 --- a/sensors/nats-events-handler.go +++ b/sensors/nats-events-handler.go @@ -63,10 +63,10 @@ func (sec *sensorExecutionCtx) successNatsSubscription(eventSource string) { common.LabelOperation: "nats_subscription_success", } if err := common.GenerateK8sEvent(sec.kubeClient, "nats subscription success", common.OperationSuccessEventType, "subscription setup", sec.sensor.Name, sec.sensor.Namespace, sec.controllerInstanceID, sensor.Kind, labels); err != nil { - sec.log.WithEventSource(eventSource).WithError(err).Error("failed to create K8s event to log nats subscription success") + sec.log.WithField(common.LabelEventSource, eventSource).WithError(err).Error("failed to create K8s event to log nats subscription success") return } - sec.log.WithEventSource(eventSource).Info("created event for nats subscription success ") + sec.log.WithField(common.LabelEventSource, eventSource).Info("created event for nats subscription success ") } func (sec *sensorExecutionCtx) escalateNatsSubscriptionFailure(eventSource string) { @@ -78,10 +78,10 @@ func (sec *sensorExecutionCtx) escalateNatsSubscriptionFailure(eventSource strin common.LabelOperation: "nats_subscription_failure", } if err := common.GenerateK8sEvent(sec.kubeClient, "nats subscription failed", common.OperationFailureEventType, "subscription setup", sec.sensor.Name, sec.sensor.Namespace, sec.controllerInstanceID, sensor.Kind, labels); err != nil { - sec.log.WithEventSource(eventSource).Error("failed to create K8s event to log nats subscription error") + sec.log.WithField(common.LabelEventSource, eventSource).Error("failed to create K8s event to log nats subscription error") return } - sec.log.WithEventSource(eventSource).Warn("created event for nats subscription failure") + sec.log.WithField(common.LabelEventSource, eventSource).Warn("created event for nats subscription failure") } // NatsEventProtocol handles events sent over NATS @@ -111,7 +111,7 @@ func (sec *sensorExecutionCtx) NatsEventProtocol() { if _, err := sec.getNatsStandardSubscription(dependency.Name); err != nil { // escalate failure sec.escalateNatsSubscriptionFailure(dependency.Name) - sec.log.WithEventSource(dependency.Name).Error("failed to get the nats subscription") + sec.log.WithField(common.LabelEventSource, dependency.Name).Error("failed to get the nats subscription") continue } dependency.Connected = true @@ -134,7 +134,7 @@ func (sec *sensorExecutionCtx) NatsEventProtocol() { } if _, err := sec.getNatsStreamingSubscription(dependency.Name); err != nil { sec.escalateNatsSubscriptionFailure(dependency.Name) - sec.log.WithEventSource(dependency.Name).WithError(err).Error("failed to get the nats subscription") + sec.log.WithField(common.LabelEventSource, dependency.Name).WithError(err).Error("failed to get the nats subscription") continue } dependency.Connected = true @@ -200,7 +200,7 @@ func (sec *sensorExecutionCtx) getNatsStreamingOption(eventSource string) (snats // processNatsMessage handles a nats message payload func (sec *sensorExecutionCtx) processNatsMessage(msg []byte, eventSource string) { - log := sec.log.WithEventSource(eventSource) + log := sec.log.WithField(common.LabelEventSource, eventSource) event, err := sec.parseEvent(msg) if err != nil { log.WithError(err).Error("failed to parse message into event") diff --git a/sensors/signal-filter.go b/sensors/signal-filter.go index f706da0a2a..fc2d6bf63d 100644 --- a/sensors/signal-filter.go +++ b/sensors/signal-filter.go @@ -62,17 +62,17 @@ func (sec *sensorExecutionCtx) filterEvent(f v1alpha1.EventDependencyFilter, eve // returns true if 1 and 2 are true and false otherwise func (sec *sensorExecutionCtx) filterTime(timeFilter *v1alpha1.TimeFilter, eventTime *metav1.MicroTime) (bool, error) { if timeFilter != nil { - sec.log.WithTime(eventTime.String()).Info("event time") + sec.log.WithField(common.LabelTime, eventTime.String()).Info("event time") utc := time.Now().UTC() currentTime := time.Date(utc.Year(), utc.Month(), utc.Day(), 0, 0, 0, 0, time.UTC).Format(common.StandardYYYYMMDDFormat) - sec.log.WithTime(currentTime).Info("current time") + sec.log.WithField(common.LabelTime, currentTime).Info("current time") if timeFilter.Start != "" && timeFilter.Stop != "" { startTime, err := time.Parse(common.StandardTimeFormat, fmt.Sprintf("%s %s", currentTime, timeFilter.Start)) if err != nil { return false, err } - sec.log.WithTime(startTime.String()).Info("start time") + sec.log.WithField(common.LabelTime, startTime.String()).Info("start time") startTime = startTime.UTC() stopTime, err := time.Parse(common.StandardTimeFormat, fmt.Sprintf("%s %s", currentTime, timeFilter.Stop)) @@ -80,7 +80,7 @@ func (sec *sensorExecutionCtx) filterTime(timeFilter *v1alpha1.TimeFilter, event return false, err } - sec.log.WithTime(stopTime.String()).Info("stop time") + sec.log.WithField(common.LabelTime, stopTime.String()).Info("stop time") stopTime = stopTime.UTC() return (startTime.Before(eventTime.Time) || stopTime.Equal(eventTime.Time)) && eventTime.Time.Before(stopTime), nil @@ -93,7 +93,7 @@ func (sec *sensorExecutionCtx) filterTime(timeFilter *v1alpha1.TimeFilter, event return false, err } - sec.log.WithTime(startTime.String()).Info("start time") + sec.log.WithField(common.LabelTime, startTime.String()).Info("start time") startTime = startTime.UTC() return startTime.Before(eventTime.Time) || startTime.Equal(eventTime.Time), nil } @@ -104,7 +104,7 @@ func (sec *sensorExecutionCtx) filterTime(timeFilter *v1alpha1.TimeFilter, event return false, err } - sec.log.WithTime(stopTime.String()).Info("stop time") + sec.log.WithField(common.LabelTime, stopTime.String()).Info("stop time") stopTime = stopTime.UTC() return eventTime.Time.Before(stopTime), nil } diff --git a/sensors/trigger.go b/sensors/trigger.go index 7a6d74e860..40b6b24a12 100644 --- a/sensors/trigger.go +++ b/sensors/trigger.go @@ -111,7 +111,7 @@ func (sec *sensorExecutionCtx) processTriggers() { successTriggerCycle := true for _, trigger := range sec.sensor.Spec.Triggers { - log := sec.log.WithTrigger(trigger.Template.Name) + log := sec.log.WithField(common.LabelTriggerName, trigger.Template.Name) // check if a trigger condition is set if canExecute := sec.canExecuteTrigger(trigger); !canExecute { diff --git a/test/e2e/common/client.go b/test/e2e/common/client.go index 76c3ce0e58..7675674a03 100644 --- a/test/e2e/common/client.go +++ b/test/e2e/common/client.go @@ -3,7 +3,6 @@ package common import ( "bytes" "fmt" - "io/ioutil" "math/rand" "net/http" "net/url" @@ -13,25 +12,17 @@ import ( "strings" "time" + gwv1 "github.com/argoproj/argo-events/pkg/apis/gateway/v1alpha1" + sv1 "github.com/argoproj/argo-events/pkg/apis/sensor/v1alpha1" + gwclient "github.com/argoproj/argo-events/pkg/client/gateway/clientset/versioned" + sensorclient "github.com/argoproj/argo-events/pkg/client/sensor/clientset/versioned" "github.com/pkg/errors" - - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - 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" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/discovery" - "k8s.io/client-go/dynamic" + "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/portforward" "k8s.io/client-go/transport/spdy" - - gwv1 "github.com/argoproj/argo-events/pkg/apis/gateway/v1alpha1" - sv1 "github.com/argoproj/argo-events/pkg/apis/sensor/v1alpha1" ) func init() { @@ -45,14 +36,15 @@ func init() { } type E2EClient struct { - Config *restclient.Config - dynamic.ClientPool - discovery.DiscoveryClient - E2EID string - ClientID string + Config *restclient.Config + KubeClient kubernetes.Interface + GwClient gwclient.Interface + SnClient sensorclient.Interface + E2EID string + ClientID string } -func NewE2EClient(e2eID string) (*E2EClient, error) { +func NewE2EClient() (*E2EClient, error) { var kubeconfig string if os.Getenv("KUBECONFIG") != "" { kubeconfig = os.Getenv("KUBECONFIG") @@ -63,209 +55,32 @@ func NewE2EClient(e2eID string) (*E2EClient, error) { if err != nil { return nil, err } - clientPool := dynamic.NewDynamicClientPool(config) - - disco, err := discovery.NewDiscoveryClientForConfig(config) - if err != nil { - return nil, err - } - - myrand := rand.New(rand.NewSource(time.Now().UnixNano())) - clientID := strconv.FormatUint(myrand.Uint64(), 16) - - return &E2EClient{ - Config: config, - ClientPool: clientPool, - DiscoveryClient: *disco, - E2EID: e2eID, - ClientID: clientID, - }, nil -} - -func (clpl *E2EClient) CreateTmpNamespace() (string, error) { - namespace := &corev1.Namespace{ - TypeMeta: metav1.TypeMeta{ - Kind: "Namespace", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - GenerateName: fmt.Sprintf("%s-", clpl.E2EID), - Labels: map[string]string{ - ArgoEventsE2ETestLabelKey: clpl.E2EID, - ArgoEventsE2ETestClientIDLabelKey: clpl.ClientID, - }, - }, - } - ns, err := clpl.Create("", namespace) - if err != nil { - return "", err - } - - nsName := ns.GetName() - binding := &rbacv1.RoleBinding{ - TypeMeta: metav1.TypeMeta{ - Kind: "RoleBinding", - APIVersion: "rbac.authorization.k8s.io/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: nsName, - Namespace: nsName, - }, - Subjects: []rbacv1.Subject{ - { - Kind: "ServiceAccount", - Name: "default", - Namespace: nsName, - }, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "ClusterRole", - Name: "argo-events-role", - }, - } - - _, err = clpl.Create(nsName, binding) - if err != nil { - return "", err - } - - return nsName, nil -} - -func (clpl *E2EClient) DeleteNamespaces() error { - client, err := clpl.GetClient("", schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Namespace"}) - if err != nil { - return err - } - // DeleteCollection is not supported for namespaces, - // so list namespaces and delete them one by one. - labelSelector := labels.Set(map[string]string{ArgoEventsE2ETestClientIDLabelKey: clpl.ClientID}).String() - obj, err := client.List(metav1.ListOptions{LabelSelector: labelSelector}) - if err != nil { - return err - } - uObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj) - if err != nil { - return err - } - for _, ns := range (unstructured.UnstructuredList{Object: uObj}).Items { - err := client.Delete(ns.GetName(), &metav1.DeleteOptions{}) - if err != nil { - return err - } - } - return nil -} - -func (clpl *E2EClient) GetClient(namespace string, gvk schema.GroupVersionKind) (dynamic.ResourceInterface, error) { - client, err := clpl.ClientPool.ClientForGroupVersionKind(gvk) - if err != nil { - return nil, err - } - - resources, err := clpl.DiscoveryClient.ServerResourcesForGroupVersion(gvk.GroupVersion().String()) - if err != nil { - return nil, err - } - - for _, resource := range resources.APIResources { - if resource.Kind == gvk.Kind { - return client.Resource(&resource, namespace), nil - } - } - - return nil, fmt.Errorf("resource not found: %v", gvk) -} - -func (clpl *E2EClient) Create(namespace string, obj runtime.Object) (*unstructured.Unstructured, error) { - uObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj) - if err != nil { - return nil, err - } - unstructuredObj := &unstructured.Unstructured{Object: uObj} - - client, err := clpl.GetClient(namespace, obj.GetObjectKind().GroupVersionKind()) - if err != nil { - return nil, err - } - - return client.Create(unstructuredObj) -} - -func (clpl *E2EClient) CreateResourceFromYaml(namespace, path string, modFunc func(*unstructured.Unstructured) error) (*unstructured.Unstructured, error) { - bytes, err := ioutil.ReadFile(path) - if err != nil { - return nil, err - } - obj, _, err := scheme.Codecs.UniversalDeserializer().Decode(bytes, nil, nil) + kubeClient, err := kubernetes.NewForConfig(config) if err != nil { return nil, err } - uObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj) + gwClient, err := gwclient.NewForConfig(config) if err != nil { return nil, err } - unstructuredObj := &unstructured.Unstructured{Object: uObj} - - if modFunc != nil { - err = modFunc(unstructuredObj) - if err != nil { - return nil, err - } - } - - return clpl.Create(namespace, unstructuredObj) -} - -func (clpl *E2EClient) Get(namespace string, gvk schema.GroupVersionKind, name string) (*unstructured.Unstructured, error) { - client, err := clpl.GetClient(namespace, gvk) + sensorClient, err := sensorclient.NewForConfig(config) if err != nil { return nil, err } - return client.Get(name, metav1.GetOptions{}) -} - -func (clpl *E2EClient) GetPod(namespace string, name string) (*corev1.Pod, error) { - client, err := clpl.GetClient(namespace, schema.GroupVersionKind{Version: "v1", Kind: "Pod"}) - if err != nil { - return nil, err - } - - uObj, err := client.Get(name, metav1.GetOptions{}) - if err != nil { - return nil, err - } - - newObj := &corev1.Pod{} - err = runtime.DefaultUnstructuredConverter.FromUnstructured(uObj.Object, newObj) - if err != nil { - return nil, err - } - return newObj, nil -} - -func (clpl *E2EClient) GetService(namespace string, name string) (*corev1.Service, error) { - client, err := clpl.GetClient(namespace, schema.GroupVersionKind{Version: "v1", Kind: "Service"}) - if err != nil { - return nil, err - } - - uObj, err := client.Get(name, metav1.GetOptions{}) - if err != nil { - return nil, err - } + myrand := rand.New(rand.NewSource(time.Now().UnixNano())) + clientID := strconv.FormatUint(myrand.Uint64(), 16) - newObj := &corev1.Service{} - err = runtime.DefaultUnstructuredConverter.FromUnstructured(uObj.Object, newObj) - if err != nil { - return nil, err - } - return newObj, nil + return &E2EClient{ + Config: config, + KubeClient: kubeClient, + GwClient: gwClient, + SnClient: sensorClient, + ClientID: clientID, + }, nil } func (clpl *E2EClient) ForwardServicePort(tmpNamespace, podName string, localPort, targetPort int) (chan struct{}, error) { diff --git a/test/e2e/common/constants.go b/test/e2e/common/constants.go deleted file mode 100644 index 47e633a158..0000000000 --- a/test/e2e/common/constants.go +++ /dev/null @@ -1,6 +0,0 @@ -package common - -const ( - ArgoEventsE2ETestLabelKey = "argo-events-e2e" - ArgoEventsE2ETestClientIDLabelKey = "argo-events-e2e-client-id" -) diff --git a/test/e2e/common/manifests/namespace.yaml b/test/e2e/common/manifests/namespace.yaml deleted file mode 100644 index 08210fa8b7..0000000000 --- a/test/e2e/common/manifests/namespace.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: "TBA" - labels: - argo-events-e2e: "TBA" - argo-events-e2e-client-id: "TBA" diff --git a/test/e2e/common/manifests/rolebinding.yaml b/test/e2e/common/manifests/rolebinding.yaml deleted file mode 100644 index 1cd6a50a0a..0000000000 --- a/test/e2e/common/manifests/rolebinding.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: "rbac.authorization.k8s.io/v1" -kind: RoleBinding -metadata: - name: "argo-events-role" - namespace: "__E2E_ID__" -subjects: -- kind: ServiceAccount - name: "default" - namespace: "__E2E_ID__" -roleRef: - apiGroup: "rbac.authorization.k8s.io" - kind: ClusterRole - name: "argo-events-role" diff --git a/test/e2e/common/misc.go b/test/e2e/common/misc.go deleted file mode 100644 index fe5c585f85..0000000000 --- a/test/e2e/common/misc.go +++ /dev/null @@ -1,28 +0,0 @@ -package common - -import ( - "os" - - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" -) - -func GetE2EID() string { - e2eID := os.Getenv("E2E_ID") - if e2eID == "" { - e2eID = "argo-events-e2e" - } - return e2eID -} - -func KeepNamespace() bool { - return os.Getenv("KEEP_NAMESPACE") != "" -} - -func SetLabel(obj *unstructured.Unstructured, key, val string) { - labels := obj.GetLabels() - if labels == nil { - labels = make(map[string]string) - } - labels[key] = val - obj.SetLabels(labels) -} diff --git a/test/e2e/core/main_test.go b/test/e2e/core/main_test.go index 2b53263cb6..737300c506 100644 --- a/test/e2e/core/main_test.go +++ b/test/e2e/core/main_test.go @@ -2,63 +2,29 @@ package core import ( "fmt" + "io/ioutil" "net" "net/http" - "os" "path/filepath" "runtime" "strings" "testing" "time" - "github.com/smartystreets/goconvey/convey" - - "github.com/argoproj/argo-events/common" + gwalpha1 "github.com/argoproj/argo-events/pkg/apis/gateway/v1alpha1" + snv1alpha1 "github.com/argoproj/argo-events/pkg/apis/sensor/v1alpha1" e2ecommon "github.com/argoproj/argo-events/test/e2e/common" + "github.com/ghodss/yaml" + "github.com/smartystreets/goconvey/convey" corev1 "k8s.io/api/core/v1" apierr "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -var ( - client *e2ecommon.E2EClient - e2eID string -) - -func setup() error { - e2eID = e2ecommon.GetE2EID() - cli, err := e2ecommon.NewE2EClient(e2eID) - if err != nil { - return err - } - client = cli - return nil -} - -func teardown() { - if !e2ecommon.KeepNamespace() { - if client != nil { - err := client.DeleteNamespaces() - if err != nil { - fmt.Printf("%+v\n", err) - } - } - } -} - -func TestMain(m *testing.M) { - err := setup() - if err != nil { - teardown() - panic(err) - } - ret := m.Run() - teardown() - os.Exit(ret) -} +const NAMESPACE = "argo-events" func TestGeneralUseCase(t *testing.T) { - tmpNamespace, err := client.CreateTmpNamespace() + client, err := e2ecommon.NewE2EClient() if err != nil { t.Fatal(err) } @@ -71,27 +37,46 @@ func TestGeneralUseCase(t *testing.T) { manifestsDir := filepath.Join(dir, "manifests", "general-use-case") convey.Convey("Test the general use case", t, func() { - convey.Convey("Create a gateway.", func() { - _, err := client.CreateResourceFromYaml(tmpNamespace, filepath.Join(manifestsDir, "webhook-gateway.yaml"), func(obj *unstructured.Unstructured) error { - e2ecommon.SetLabel(obj, common.LabelKeyGatewayControllerInstanceID, e2eID) - return nil - }) + + convey.Convey("Create event source", func() { + esBytes, err := ioutil.ReadFile(filepath.Join(manifestsDir, "webhook-gateway-event-source.yaml")) if err != nil { - t.Fatal(err) + convey.ShouldPanic(err) + } + var cm *corev1.ConfigMap + if err := yaml.Unmarshal(esBytes, &cm); err != nil { + convey.ShouldPanic(err) } - _, err = client.CreateResourceFromYaml(tmpNamespace, filepath.Join(manifestsDir, "webhook-gateway-configmap.yaml"), nil) + if _, err = client.KubeClient.CoreV1().ConfigMaps(NAMESPACE).Create(cm); err != nil { + convey.ShouldPanic(err) + } + }) + + convey.Convey("Create a gateway.", func() { + gwBytes, err := ioutil.ReadFile(filepath.Join(manifestsDir, "webhook-gateway.yaml")) if err != nil { - t.Fatal(err) + convey.ShouldPanic(err) + } + var gw *gwalpha1.Gateway + if err := yaml.Unmarshal(gwBytes, &gw); err != nil { + convey.ShouldPanic(err) + } + if _, err = client.GwClient.ArgoprojV1alpha1().Gateways(NAMESPACE).Create(gw); err != nil { + convey.ShouldPanic(err) } }) convey.Convey("Create a sensor.", func() { - _, err := client.CreateResourceFromYaml(tmpNamespace, filepath.Join(manifestsDir, "webhook-sensor.yaml"), func(obj *unstructured.Unstructured) error { - e2ecommon.SetLabel(obj, common.LabelKeySensorControllerInstanceID, e2eID) - return nil - }) + swBytes, err := ioutil.ReadFile(filepath.Join(manifestsDir, "webhook-sensor.yaml")) if err != nil { - t.Fatal(err) + convey.ShouldPanic(err) + } + var sn *snv1alpha1.Sensor + if err := yaml.Unmarshal(swBytes, &sn); err != nil { + convey.ShouldPanic(err) + } + if _, err = client.SnClient.ArgoprojV1alpha1().Sensors(NAMESPACE).Create(sn); err != nil { + convey.ShouldPanic(err) } }) @@ -100,48 +85,37 @@ func TestGeneralUseCase(t *testing.T) { defer ticker.Stop() var gwpod, spod *corev1.Pod var gwsvc *corev1.Service - L: for { - select { - case _ = <-ticker.C: - if gwpod == nil { - pod, err := client.GetPod(tmpNamespace, "webhook-gateway") - if err != nil && !apierr.IsNotFound(err) { - t.Error(err) - break L - } - if pod != nil && pod.Status.Phase == corev1.PodRunning { - gwpod = pod - } + if gwpod == nil { + pod, err := client.KubeClient.CoreV1().Pods(NAMESPACE).Get("webhook-gateway", metav1.GetOptions{}) + if err != nil && !apierr.IsNotFound(err) { + t.Fatal(err) + } + _, _ = yaml.Marshal(pod) + if pod != nil && pod.Status.Phase == corev1.PodRunning { + gwpod = pod } - if gwsvc == nil { - svc, err := client.GetService(tmpNamespace, "webhook-gateway-svc") - if err != nil && !apierr.IsNotFound(err) { - t.Error(err) - break L - } - gwsvc = svc + } + + if gwsvc == nil { + svc, err := client.KubeClient.CoreV1().Services(NAMESPACE).Get("webhook-gateway-svc", metav1.GetOptions{}) + if err != nil && !apierr.IsNotFound(err) { + t.Fatal(err) } - if spod == nil { - pod, err := client.GetPod(tmpNamespace, "webhook-sensor") - if err != nil && !apierr.IsNotFound(err) { - t.Error(err) - break L - } - if pod != nil && pod.Status.Phase == corev1.PodRunning { - spod = pod - } + gwsvc = svc + } + if spod == nil { + pod, err := client.KubeClient.CoreV1().Pods(NAMESPACE).Get("webhook-sensor", metav1.GetOptions{}) + if err != nil && !apierr.IsNotFound(err) { + t.Fatal(err) } - if gwpod != nil && gwsvc != nil && spod != nil { - break L + if pod != nil && pod.Status.Phase == corev1.PodRunning { + spod = pod } - case <-time.After(10 * time.Second): - t.Error("timed out gateway and sensor startup") - break L } - } - if t.Failed() { - t.FailNow() + if gwpod != nil && gwsvc != nil && spod != nil { + break + } } }) @@ -155,7 +129,7 @@ func TestGeneralUseCase(t *testing.T) { l.Close() // Use port forwarding to access pods in minikube - stopChan, err := client.ForwardServicePort(tmpNamespace, "webhook-gateway", port, 12000) + stopChan, err := client.ForwardServicePort(NAMESPACE, "webhook-gateway", port, 12000) if err != nil { t.Fatal(err) } @@ -179,25 +153,12 @@ func TestGeneralUseCase(t *testing.T) { }) convey.Convey("Check if the sensor trigggered a pod.", func() { - ticker2 := time.NewTicker(time.Second) - defer ticker2.Stop() - L: - for { - select { - case _ = <-ticker2.C: - pod, err := client.GetPod(tmpNamespace, "webhook-sensor-triggered-pod") - if err != nil && !apierr.IsNotFound(err) { - t.Error(err) - break L - } - if pod != nil && pod.Status.Phase == corev1.PodSucceeded { - convey.So(pod.Spec.Containers[0].Args[0], convey.ShouldEqual, "e2e") - break L - } - case <-time.After(10 * time.Second): - t.Error("timed out gateway and sensor startup") - break L - } + pod, err := client.KubeClient.CoreV1().Pods(NAMESPACE).Get("webhook-sensor-triggered-pod", metav1.GetOptions{}) + if err != nil && !apierr.IsNotFound(err) { + t.Error(err) + } + if pod != nil && pod.Status.Phase == corev1.PodSucceeded { + convey.So(pod.Spec.Containers[0].Args[0], convey.ShouldEqual, "e2e") } }) }) diff --git a/test/e2e/core/manifests/general-use-case/webhook-gateway-configmap.yaml b/test/e2e/core/manifests/general-use-case/webhook-gateway-configmap.yaml deleted file mode 100644 index 2f49c9d6f0..0000000000 --- a/test/e2e/core/manifests/general-use-case/webhook-gateway-configmap.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: webhook-gateway-configmap -data: - foo: |- - port: "12000" - endpoint: "/foo" - method: "POST" diff --git a/test/e2e/core/manifests/general-use-case/webhook-gateway-event-source.yaml b/test/e2e/core/manifests/general-use-case/webhook-gateway-event-source.yaml new file mode 100644 index 0000000000..a49b99b8ca --- /dev/null +++ b/test/e2e/core/manifests/general-use-case/webhook-gateway-event-source.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: webhook-event-source + labels: + # do not remove + argo-events-event-source-version: v0.10 +data: + foo: |- + # port to run HTTP server on + port: "12000" + # endpoint to listen to + endpoint: "/index" + # HTTP request method to allow. In this case, only POST requests are accepted + method: "POST" diff --git a/test/e2e/core/manifests/general-use-case/webhook-gateway.yaml b/test/e2e/core/manifests/general-use-case/webhook-gateway.yaml index 588dbe745c..414d0cdb3a 100644 --- a/test/e2e/core/manifests/general-use-case/webhook-gateway.yaml +++ b/test/e2e/core/manifests/general-use-case/webhook-gateway.yaml @@ -3,16 +3,19 @@ kind: Gateway metadata: name: webhook-gateway labels: - gateways.argoproj.io/gateway-controller-instanceid: "__E2E_ID__" + # gateway controller with instanceId "argo-events" will process this gateway + gateways.argoproj.io/gateway-controller-instanceid: argo-events + # gateway controller will use this label to match with it's own version + # do not remove + argo-events-gateway-version: v0.10 spec: - configMap: "webhook-gateway-configmap" type: "webhook" + eventSource: "webhook-event-source" processorPort: "9330" eventProtocol: type: "HTTP" http: port: "9300" - eventVersion: "1.0" template: metadata: name: "webhook-gateway" @@ -21,18 +24,26 @@ spec: spec: containers: - name: "gateway-client" - image: "argoproj/gateway-client" - imagePullPolicy: "IfNotPresent" + image: "argoproj/gateway-client:v0.10-test" + imagePullPolicy: "Always" command: ["/bin/gateway-client"] - name: "webhook-events" - image: "argoproj/webhook-gateway" - imagePullPolicy: "IfNotPresent" + image: "argoproj/webhook-gateway:v0.10-test" + imagePullPolicy: "Always" command: ["/bin/webhook-gateway"] - # ports: - # - containerPort: 12000 + # To make webhook secure, mount the secret that contains certificate and private key in the container + # and refer that mountPath in the event source. + # volumeMounts: + # - mountPath: "/bin/webhook-secure" + # name: secure + # volumes: + # - name: secure + # secret: + # secretName: webhook-secure + serviceAccountName: "argo-events-sa" service: metadata: - name: "webhook-gateway-svc" + name: webhook-gateway-svc spec: selector: gateway-name: "webhook-gateway" diff --git a/test/e2e/core/manifests/general-use-case/webhook-sensor.yaml b/test/e2e/core/manifests/general-use-case/webhook-sensor.yaml index adfab2bbfd..d52abbd251 100644 --- a/test/e2e/core/manifests/general-use-case/webhook-sensor.yaml +++ b/test/e2e/core/manifests/general-use-case/webhook-sensor.yaml @@ -3,14 +3,18 @@ kind: Sensor metadata: name: webhook-sensor labels: - sensors.argoproj.io/sensor-controller-instanceid: "__E2E_ID__" + sensors.argoproj.io/sensor-controller-instanceid: argo-events + # sensor controller will use this label to match with it's own version + # do not remove + argo-events-sensor-version: v0.10 spec: template: spec: containers: - name: "sensor" - image: "argoproj/sensor" + image: "argoproj/sensor:v0.10-test" imagePullPolicy: "IfNotPresent" + serviceAccountName: argo-events-sa dependencies: - name: "webhook-gateway:foo" eventProtocol: diff --git a/version.go b/version.go index 3ac868a1d5..8ad31e0a05 100644 --- a/version.go +++ b/version.go @@ -24,7 +24,7 @@ import ( // Version information set by link flags during build. We fall back to these sane // default values when we build outside the Makefile context (e.g. go build or go test). var ( - version = "v0.9" // value from VERSION file + version = "v0.10" // value from VERSION file buildDate = "1970-01-01T00:00:00Z" // output from `date -u +'%Y-%m-%dT%H:%M:%SZ'` gitCommit = "" // output from `git rev-parse HEAD` gitTag = "" // output from `git describe --exact-match --tags HEAD` (if clean tree state)

Gateway @@ -108,14 +109,14 @@ The framework code acts as a gRPC client consuming event stream from gateway ser * ### Available Environment Variables to Server - | Field | Description | - |----------------------|--------------| - | GATEWAY_NAMESPACE | K8s namespace of the gateway | - | GATEWAY_EVENT_SOURCE_CONFIG_MAP | K8s configmap containing event source| - | GATEWAY_NAME | name of the gateway | - | GATEWAY_CONTROLLER_INSTANCE_ID | gateway controller instance id | - | GATEWAY_CONTROLLER_NAME | gateway controller name - | GATEWAY_SERVER_PORT | Port on which the gateway gRPC server should run + | Field | Description | + | ------------------------------- | ------------------------------------------------ | + | GATEWAY_NAMESPACE | K8s namespace of the gateway | + | GATEWAY_EVENT_SOURCE_CONFIG_MAP | K8s configmap containing event source | + | GATEWAY_NAME | name of the gateway | + | GATEWAY_CONTROLLER_INSTANCE_ID | gateway controller instance id | + | GATEWAY_CONTROLLER_NAME | gateway controller name | + | GATEWAY_SERVER_PORT | Port on which the gateway gRPC server should run | * ### Implementation You can follow existing implementations [here](../gateways) diff --git a/docs/gateway-protocol.md b/docs/gateway-protocol.md deleted file mode 100644 index 81933fdf58..0000000000 --- a/docs/gateway-protocol.md +++ /dev/null @@ -1,223 +0,0 @@ -# Protocol Documentation - - -## Table of Contents - -- [pkg/apis/gateway/v1alpha1/generated.proto](#pkg/apis/gateway/v1alpha1/generated.proto) - - [Gateway](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.Gateway) - - [GatewayList](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.GatewayList) - - [GatewayNotificationWatcher](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.GatewayNotificationWatcher) - - [GatewaySpec](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.GatewaySpec) - - [GatewayStatus](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.GatewayStatus) - - [GatewayStatus.NodesEntry](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.GatewayStatus.NodesEntry) - - [NodeStatus](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.NodeStatus) - - [NotificationWatchers](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.NotificationWatchers) - - [SensorNotificationWatcher](#github.com.argoproj.argo_events.pkg.apis.gateway.v1alpha1.SensorNotificationWatcher) - - - - - -- [Scalar Value Types](#scalar-value-types) - - - - -