diff --git a/Makefile b/Makefile index 42df80f4c3..fc57e342af 100644 --- a/Makefile +++ b/Makefile @@ -197,9 +197,9 @@ plugin-darwin: ui/dist cp -r ui/dist/app/* server/static CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -v -i -ldflags '${LDFLAGS}' -o ${DIST_DIR}/${PLUGIN_CLI_NAME}-darwin-amd64 ./cmd/kubectl-argo-rollouts -.PHONY: plugin-docs -plugin-docs: - go run ./hack/gen-plugin-docs/main.go +.PHONY: docs +docs: + go run ./hack/gen-docs/main.go .PHONY: builder-image builder-image: @@ -259,7 +259,7 @@ clean: precheckin: test lint .PHONY: release-docs -release-docs: plugin-docs +release-docs: docs docker run --rm -it \ -v ~/.ssh:/root/.ssh \ -v ${CURRENT_DIR}:/docs \ diff --git a/cmd/rollouts-controller/main.go b/cmd/rollouts-controller/main.go index 41ed2a2c92..98090e7bce 100644 --- a/cmd/rollouts-controller/main.go +++ b/cmd/rollouts-controller/main.go @@ -135,6 +135,13 @@ func newCommand() *cobra.Command { clusterDynamicInformerFactory := dynamicinformer.NewFilteredDynamicSharedInformerFactory(dynamicClient, resyncDuration, metav1.NamespaceAll, instanceIDTweakListFunc) // 3. We finally need an istio dynamic informer factory which does not use a tweakListFunc. istioDynamicInformerFactory := dynamicinformer.NewFilteredDynamicSharedInformerFactory(dynamicClient, resyncDuration, namespace, nil) + + controllerNamespaceInformerFactory := kubeinformers.NewSharedInformerFactoryWithOptions( + kubeClient, + resyncDuration, + kubeinformers.WithNamespace(defaults.Namespace())) + configMapInformer := controllerNamespaceInformerFactory.Core().V1().ConfigMaps() + secretInformer := controllerNamespaceInformerFactory.Core().V1().Secrets() cm := controller.NewManager( namespace, kubeClient, @@ -153,6 +160,8 @@ func newCommand() *cobra.Command { tolerantinformer.NewTolerantClusterAnalysisTemplateInformer(clusterDynamicInformerFactory), istioDynamicInformerFactory.ForResource(istioutil.GetIstioVirtualServiceGVR()).Informer(), istioDynamicInformerFactory.ForResource(istioutil.GetIstioDestinationRuleGVR()).Informer(), + configMapInformer, + secretInformer, resyncDuration, instanceID, metricsPort, @@ -166,6 +175,7 @@ func newCommand() *cobra.Command { clusterDynamicInformerFactory.Start(stopCh) } kubeInformerFactory.Start(stopCh) + controllerNamespaceInformerFactory.Start(stopCh) jobInformerFactory.Start(stopCh) // Check if Istio installed on cluster before starting dynamicInformerFactory diff --git a/controller/controller.go b/controller/controller.go index 997e9202a0..578ed2a59d 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -1,15 +1,17 @@ package controller import ( + "encoding/json" "fmt" "time" - "github.com/argoproj/argo-rollouts/utils/queue" - + "github.com/argoproj/notifications-engine/pkg/api" + "github.com/argoproj/notifications-engine/pkg/controller" "github.com/pkg/errors" smiclientset "github.com/servicemeshinterface/smi-sdk-go/pkg/gen/client/split/clientset/versioned" log "github.com/sirupsen/logrus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" @@ -28,11 +30,14 @@ import ( "github.com/argoproj/argo-rollouts/controller/metrics" "github.com/argoproj/argo-rollouts/experiments" "github.com/argoproj/argo-rollouts/ingress" + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" clientset "github.com/argoproj/argo-rollouts/pkg/client/clientset/versioned" rolloutscheme "github.com/argoproj/argo-rollouts/pkg/client/clientset/versioned/scheme" informers "github.com/argoproj/argo-rollouts/pkg/client/informers/externalversions/rollouts/v1alpha1" "github.com/argoproj/argo-rollouts/rollout" "github.com/argoproj/argo-rollouts/service" + "github.com/argoproj/argo-rollouts/utils/defaults" + "github.com/argoproj/argo-rollouts/utils/queue" "github.com/argoproj/argo-rollouts/utils/record" ) @@ -61,12 +66,13 @@ const ( // Manager is the controller implementation for Argo-Rollout resources type Manager struct { - metricsServer *metrics.MetricsServer - rolloutController *rollout.Controller - experimentController *experiments.Controller - analysisController *analysis.Controller - serviceController *service.Controller - ingressController *ingress.Controller + metricsServer *metrics.MetricsServer + rolloutController *rollout.Controller + experimentController *experiments.Controller + analysisController *analysis.Controller + serviceController *service.Controller + ingressController *ingress.Controller + notificationsController controller.NotificationController rolloutSynced cache.InformerSynced experimentSynced cache.InformerSynced @@ -77,6 +83,8 @@ type Manager struct { ingressSynced cache.InformerSynced jobSynced cache.InformerSynced replicasSetSynced cache.InformerSynced + configMapSynced cache.InformerSynced + secretSynced cache.InformerSynced rolloutWorkqueue workqueue.RateLimitingInterface serviceWorkqueue workqueue.RateLimitingInterface @@ -110,6 +118,8 @@ func NewManager( clusterAnalysisTemplateInformer informers.ClusterAnalysisTemplateInformer, istioVirtualServiceInformer cache.SharedIndexInformer, istioDestinationRuleInformer cache.SharedIndexInformer, + configMapInformer coreinformers.ConfigMapInformer, + secretInformer coreinformers.SecretInformer, resyncPeriod time.Duration, instanceID string, metricsPort int, @@ -139,8 +149,22 @@ func NewManager( ingressWorkqueue := workqueue.NewNamedRateLimitingQueue(queue.DefaultArgoRolloutsRateLimiter(), "Ingresses") refResolver := rollout.NewInformerBasedWorkloadRefResolver(namespace, dynamicclientset, discoveryClient, rolloutWorkqueue, rolloutsInformer.Informer()) - - recorder := record.NewEventRecorder(kubeclientset, metrics.MetricRolloutEventsTotal) + apiFactory := api.NewFactory(record.NewAPIFactorySettings(), defaults.Namespace(), secretInformer.Informer(), configMapInformer.Informer()) + recorder := record.NewEventRecorder(kubeclientset, metrics.MetricRolloutEventsTotal, apiFactory) + notificationsController := controller.NewController(dynamicclientset.Resource(v1alpha1.RolloutGVR), rolloutsInformer.Informer(), apiFactory, + controller.WithToUnstructured(func(obj metav1.Object) (*unstructured.Unstructured, error) { + data, err := json.Marshal(obj) + if err != nil { + return nil, err + } + res := &unstructured.Unstructured{} + err = json.Unmarshal(data, res) + if err != nil { + return nil, err + } + return res, nil + }), + ) rolloutController := rollout.NewController(rollout.ControllerConfig{ Namespace: namespace, @@ -229,6 +253,8 @@ func NewManager( analysisTemplateSynced: analysisTemplateInformer.Informer().HasSynced, clusterAnalysisTemplateSynced: clusterAnalysisTemplateInformer.Informer().HasSynced, replicasSetSynced: replicaSetInformer.Informer().HasSynced, + configMapSynced: configMapInformer.Informer().HasSynced, + secretSynced: secretInformer.Informer().HasSynced, rolloutWorkqueue: rolloutWorkqueue, experimentWorkqueue: experimentWorkqueue, analysisRunWorkqueue: analysisRunWorkqueue, @@ -239,6 +265,7 @@ func NewManager( ingressController: ingressController, experimentController: experimentController, analysisController: analysisController, + notificationsController: notificationsController, dynamicClientSet: dynamicclientset, refResolver: refResolver, namespace: namespace, @@ -260,7 +287,7 @@ func (c *Manager) Run(rolloutThreadiness, serviceThreadiness, ingressThreadiness // Wait for the caches to be synced before starting workers log.Info("Waiting for controller's informer caches to sync") - if ok := cache.WaitForCacheSync(stopCh, c.serviceSynced, c.ingressSynced, c.jobSynced, c.rolloutSynced, c.experimentSynced, c.analysisRunSynced, c.analysisTemplateSynced, c.replicasSetSynced); !ok { + if ok := cache.WaitForCacheSync(stopCh, c.serviceSynced, c.ingressSynced, c.jobSynced, c.rolloutSynced, c.experimentSynced, c.analysisRunSynced, c.analysisTemplateSynced, c.replicasSetSynced, c.configMapSynced, c.secretSynced); !ok { return fmt.Errorf("failed to wait for caches to sync") } // only wait for cluster scoped informers to sync if we are running in cluster-wide mode @@ -277,6 +304,8 @@ func (c *Manager) Run(rolloutThreadiness, serviceThreadiness, ingressThreadiness go wait.Until(func() { c.ingressController.Run(ingressThreadiness, stopCh) }, time.Second, stopCh) go wait.Until(func() { c.experimentController.Run(experimentThreadiness, stopCh) }, time.Second, stopCh) go wait.Until(func() { c.analysisController.Run(analysisThreadiness, stopCh) }, time.Second, stopCh) + go wait.Until(func() { c.notificationsController.Run(rolloutThreadiness, stopCh) }, time.Second, stopCh) + log.Info("Started controller") go func() { diff --git a/docs/features/notifications.md b/docs/features/notifications.md new file mode 100644 index 0000000000..b33f05507f --- /dev/null +++ b/docs/features/notifications.md @@ -0,0 +1,134 @@ +# Notifications + +!!! important + Available since v1.1 + +Argo Rollouts provides notifications powered by the [Notifications Engine](https://github.com/argoproj/notifications-engine). +Controller administrators can leverage flexible systems of triggers and templates to configure notifications requested +by the end users. The end-users can subscribe to the configured triggers by adding an annotation to the Rollout objects. + +## Configuration + +The trigger defines the condition when the notification should be sent as well as the notification content template. +Default Argo Rollouts comes with a list of built-in triggers that cover the most important events of Argo Rollout live-cycle. +Both triggers and templates are configured in the `argo-rollouts-notification-configmap` ConfigMap. In order to get +started quickly, you can use pre-configured notification templates defined in [notifications-install.yaml](../../manifests/notifications-install.yaml). + +If you are leveraging Kustomize it is recommended to include [notifications-install.yaml](../../manifests/notifications-install.yaml) as a remote +resource into your `kustomization.yaml` file: + +```yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml +- https://github.com/argoproj/argo-rollouts/releases/latest/download/notifications-install.yaml +``` + +After including the `argo-rollouts-notification-configmap` ConfigMap the administrator needs to configure integration +with the required notifications service such as Slack or MS Teams. An example below demonstrates Slack integration: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: argo-rollouts-notification-configmap +data: + service.slack: | + token: $slack-token +--- +apiVersion: v1 +kind: Secret +metadata: + name: argo-rollouts-notification-secret +stringData: + slack-token: +``` + +Learn more about supported services and configuration settings in services [documentation](../generated/notification-services/overview.md). + +## Subscriptions + +The end-users can start leveraging notifications using `notifications.argoproj.io/subscribe..: ` annotation. +For example, the following annotation subscribes two Slack channels to notifications about canary rollout step completion: + +```yaml +--- +apiVersion: argoproj.io/v1alpha1 +kind: Rollout +metadata: + name: rollout-canary + annotations: + notifications.argoproj.io/subscribe.on-rollout-step-completed.slack: my-channel1;my-channel2 + +``` + +Annotation key consists of following parts: + +* `on-rollout-step-completed` - trigger name +* `slack` - notification service name +* `my-channel1;my-channel2` - a semicolon separated list of recipients + +## Customization + +The Rollout administrator can customize the notifications by configuring notification templates and custom triggers +in `argo-rollouts-notification-configmap` ConfigMap. + +### Templates + +The notification template is a stateless function that generates the notification content. The template is leveraging +[html/template](https://golang.org/pkg/html/template/) golang package. It is meant to be reusable and can be referenced by multiple triggers. + +An example below demonstrates a sample template: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: argo-rollouts-notification-configmap +data: + template.my-purple-template: | + message: | + Rollout {{.rollout.metadata.name}} has purple image + slack: + attachments: | + [{ + "title": "{{ .rollout.metadata.name}}", + "color": "#800080" + }] +``` + +Each template has access to the following fields: + +- `rollout` holds the rollout object. +- `recipient` holds the recipient name. + +The `message` field of the template definition allows creating a basic notification for any notification service. You can +leverage notification service-specific fields to create complex notifications. For example using service-specific you can +add blocks and attachments for Slack, subject for Email or URL path, and body for Webhook. See corresponding service +[documentation](../generated/notification-services/overview.md) for more information. + +### Custom Triggers + +In addition to custom notification template administrator and configure custom triggers. Custom trigger defines the +condition when the notification should be sent. The definition includes name, condition and notification templates reference. +The condition is a predicate expression that returns true if the notification should be sent. The trigger condition +evaluation is powered by [antonmedv/expr](https://github.com/antonmedv/expr). +The condition language syntax is described at [Language-Definition.md](https://github.com/antonmedv/expr/blob/master/docs/Language-Definition.md). + +The trigger is configured in `argo-rollouts-notification-configmap` ConfigMap. For example the following trigger sends a notification +when rollout pod spec uses `argoproj/rollouts-demo:purple` image: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: argocd-notifications-cm +data: + trigger.on-purple: | + - send: [my-purple-template] + when: rollout.spec.template.spec.containers[0].image == 'argoproj/rollouts-demo:purple' +``` + +Each condition might use several templates. Typically each template is responsible for generating a service-specific notification part. diff --git a/examples/notifications/configmap.yaml b/examples/notifications/configmap.yaml new file mode 100644 index 0000000000..a462f24943 --- /dev/null +++ b/examples/notifications/configmap.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: argo-rollouts-notification-configmap +data: + service.slack: | + token: $slack-token + ## Custom Trigger + trigger.on-purple: | + - send: [my-purple-template] + when: rollout.spec.template.spec.containers[0].image == 'argoproj/rollouts-demo:purple' + template.my-purple-template: | + message: | + Rollout {{.rollout.metadata.name}} has purple image + slack: + attachments: | + [{ + "title": "{{ .rollout.metadata.name}}", + "color": "#800080" + }] \ No newline at end of file diff --git a/examples/notifications/kustomization.yaml b/examples/notifications/kustomization.yaml new file mode 100644 index 0000000000..df8b1ffb2f --- /dev/null +++ b/examples/notifications/kustomization.yaml @@ -0,0 +1,8 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- ../../manifests/notifications + +patchesStrategicMerge: +- configmap.yaml \ No newline at end of file diff --git a/examples/notifications/rollout-canary.yaml b/examples/notifications/rollout-canary.yaml new file mode 100644 index 0000000000..fe3191c9b4 --- /dev/null +++ b/examples/notifications/rollout-canary.yaml @@ -0,0 +1,73 @@ +# This example demonstrates a Rollout using the canary update strategy with a customized rollout +# plan. The prescribed steps initially sets a canary weight of 20%, then pauses indefinitely. Once +# resumed, the rollout performs a gradual, automated 20% weight increase until it reaches 100%. +apiVersion: v1 +kind: Service +metadata: + name: rollouts-canary +spec: + type: LoadBalancer + ports: + - port: 8080 + targetPort: 8080 + protocol: TCP + name: http + selector: + app: rollout-canary +--- +apiVersion: networking.k8s.io/v1beta1 +kind: Ingress +metadata: + name: rollouts-demo-stable + annotations: + kubernetes.io/ingress.class: nginx +spec: + rules: + - http: + paths: + - path: / + backend: + # Reference to a Service name, also specified in the Rollout spec.strategy.canary.stableService field + serviceName: rollouts-canary + servicePort: 8080 +--- +apiVersion: argoproj.io/v1alpha1 +kind: Rollout +metadata: + name: rollout-canary + annotations: + notifications.argoproj.io/subscribe.on-rollout-completed.slack: argoproj-deployments-notifications + notifications.argoproj.io/subscribe.on-rollout-step-completed.slack: argoproj-deployments-notifications + notifications.argoproj.io/subscribe.on-rollout-updated.slack: argoproj-deployments-notifications + notifications.argoproj.io/subscribe.on-scaling-replica-set.slack: argoproj-deployments-notifications + notifications.argoproj.io/subscribe.on-purple.slack: argoproj-deployments-notifications +spec: + replicas: 5 + revisionHistoryLimit: 2 + selector: + matchLabels: + app: rollout-canary + template: + metadata: + labels: + app: rollout-canary + spec: + containers: + - name: rollouts-demo + image: argoproj/rollouts-demo:blue + imagePullPolicy: Always + ports: + - containerPort: 8080 + strategy: + canary: + steps: + - setWeight: 20 + # The following pause step will pause the rollout indefinitely until manually resumed. + # Rollouts can be manually resumed by running `kubectl argo rollouts promote ROLLOUT` + - pause: {} + - setWeight: 40 + - pause: {duration: 10s} + - setWeight: 60 + - pause: {duration: 10s} + - setWeight: 80 + - pause: {duration: 10s} diff --git a/go.mod b/go.mod index b82d4c6e1d..465d5f78f5 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.16 require ( github.com/antonmedv/expr v1.8.9 + github.com/argoproj/notifications-engine v0.2.1-0.20210525191332-e8e293898477 github.com/argoproj/pkg v0.9.0 github.com/aws/aws-sdk-go-v2/config v1.0.0 github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.0.0 @@ -12,6 +13,7 @@ require ( github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 github.com/go-openapi/spec v0.19.3 github.com/gogo/protobuf v1.3.2 + github.com/golang/mock v1.4.4 github.com/golang/protobuf v1.4.3 github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 @@ -28,7 +30,7 @@ require ( github.com/sirupsen/logrus v1.7.0 github.com/soheilhy/cmux v0.1.4 github.com/spaceapegames/go-wavefront v1.8.1 - github.com/spf13/cobra v1.1.1 + github.com/spf13/cobra v1.1.3 github.com/stretchr/testify v1.7.0 github.com/tj/assert v0.0.3 github.com/undefinedlabs/go-mpatch v1.0.6 @@ -56,6 +58,7 @@ require ( ) replace ( + github.com/go-check/check => github.com/go-check/check v0.0.0-20180628173108-788fd7840127 github.com/grpc-ecosystem/grpc-gateway => github.com/grpc-ecosystem/grpc-gateway v1.16.0 k8s.io/api => k8s.io/api v0.20.4 k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.20.4 diff --git a/go.sum b/go.sum index c705268a3e..ed672b8a52 100644 --- a/go.sum +++ b/go.sum @@ -99,12 +99,17 @@ github.com/Djarvur/go-err113 v0.0.0-20200511133814-5174e21577d5/go.mod h1:4UJr5H github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo= github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20200415212048-7901bc822317/go.mod h1:DF8FZRxMHMGv/vP2lQP6h+dYzzjpuRn24VeRiYn3qjQ= github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5hodBMJ5+l/7J4xAyMeuM2PNuepvHlGs8yilUCA= +github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo= +github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= +github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Masterminds/sprig/v3 v3.1.0/go.mod h1:ONGMf7UfYGAbMXCZmQLy8x3lCDIPrEZE/rU8pmrbihA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= @@ -120,6 +125,8 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20210112200207-10ab4d695d60 h1:prBTRx78AQnXzivNT9Crhu564W/zPPr3ibSlpT9xKcE= +github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20210112200207-10ab4d695d60/go.mod h1:rjP7sIipbZcagro/6TCk6X0ZeFT2eyudH5+fve/cbBA= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= @@ -146,6 +153,9 @@ github.com/apex/log v1.9.0/go.mod h1:m82fZlWIuiWzWP04XCTXmnX0xRkYYbCdYn8jbJeLBEA github.com/apex/logs v1.0.0/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo= github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE= github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= +github.com/appscode/go v0.0.0-20190808133642-1d4ef1f1c1e0/go.mod h1:iy07dV61Z7QQdCKJCIvUoDL21u6AIceRhZzyleh2ymc= +github.com/argoproj/notifications-engine v0.2.1-0.20210525191332-e8e293898477 h1:mcfUn59PKafSlbkZ39+aQAIzoAsYzjVR61O6Ns/Dfzo= +github.com/argoproj/notifications-engine v0.2.1-0.20210525191332-e8e293898477/go.mod h1:rKhm9LtebGKgLA/UtPtBeRUrrS/CT0U5az1jSfUiipw= github.com/argoproj/pkg v0.9.0 h1:PfWWYykfcEQdN0g41XLbVh/aonTjD+dPkvDp3hwpLYM= github.com/argoproj/pkg v0.9.0/go.mod h1:ra+bQPmbVAoEL+gYSKesuigt4m49i3Qa3mE/xQcjCiA= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -183,6 +193,7 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.0.0/go.mod h1:5f+cELGATgill5Pu3/vK3E github.com/aws/smithy-go v1.0.0 h1:hkhcRKG9rJ4Fn+RbfXY7Tz7b3ITLDyolBnLLBhwbg/c= github.com/aws/smithy-go v1.0.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= +github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -196,6 +207,9 @@ github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdn github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/bombsimon/wsl/v3 v3.1.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= +github.com/bradleyfalzon/ghinstallation v1.1.1 h1:pmBXkxgM1WeF8QYvDLT5kuQiHMcmf+X015GI0KM/E3I= +github.com/bradleyfalzon/ghinstallation v1.1.1/go.mod h1:vyCmHTciHx/uuyN82Zc3rXN3X2KTK8nUTCrTMwAhcug= +github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= github.com/caarlos0/ctrlc v1.0.0/go.mod h1:CdXpj4rmq0q/1Eb44M9zi2nKB0QraNKuRGYGrrHhcQw= github.com/caddyserver/caddy v1.0.3/go.mod h1:G+ouvOY32gENkJC+jhgl62TyhvqEsFaDiZ4uw0RzP1E= github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMSc6E5ydlp5NIonxObaeu/Iub/X03EKPVYo= @@ -223,7 +237,9 @@ github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1w github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= +github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE= github.com/container-storage-interface/spec v1.2.0/go.mod h1:6URME8mwIBbpVyZV93Ce5St17xBiQJQY67NDsuohiy4= github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= @@ -263,8 +279,10 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= +github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/denis-tingajkin/go-header v0.3.1/go.mod h1:sq/2IxMhaZX+RRcgHfCRx/m0M5na0fBt4/CRe7Lrji0= github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= @@ -305,12 +323,16 @@ github.com/evanphx/json-patch/v5 v5.2.0 h1:8ozOH5xxoMYDt5/u+yMTsVXydVCbTORFnOOoq github.com/evanphx/json-patch/v5 v5.2.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= +github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/flosch/pongo2 v0.0.0-20181225140029-79872a7b2769/go.mod h1:tbAXHifHQWNSpWbiJHpJTZH5fi3XHhDMdP//vuz9WS4= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= @@ -335,6 +357,7 @@ github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0 github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-acme/lego v2.5.0+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= github.com/go-bindata/go-bindata v3.1.1+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-critic/go-critic v0.5.0/go.mod h1:4jeRh3ZAVnRYhuWdOEvwzVqLUpxMSoAT0xZ74JsTPlo= github.com/go-critic/go-critic v0.5.2/go.mod h1:cc0+HvdE3lFpqLecgqMaJcvWWH77sLdBp+wLGPM1Yyo= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= @@ -356,6 +379,7 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.3.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= @@ -406,6 +430,10 @@ github.com/go-ozzo/ozzo-validation v3.5.0+incompatible/go.mod h1:gsEKFIVnabGBt6m github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= +github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= +github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= @@ -421,6 +449,7 @@ github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslW github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= @@ -447,6 +476,8 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -498,6 +529,10 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM= +github.com/google/go-github/v29 v29.0.2 h1:opYN6Wc7DOz7Ku3Oh4l7prmkOMwEcQxpFtxdU8N8Pts= +github.com/google/go-github/v29 v29.0.2/go.mod h1:CHKiKKPHJ0REzfwc14QMklvtHwCveD0PxlMjLlzAM5E= +github.com/google/go-github/v33 v33.0.0 h1:qAf9yP0qc54ufQxzwv+u9H0tiVOnPJxo0lI/JXqw3ZM= +github.com/google/go-github/v33 v33.0.0/go.mod h1:GMdDnVZY/2TsWgp/lkYnpSAh6TrzhANBBwm6k6TTEXg= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE= @@ -533,6 +568,8 @@ github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyyc github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/gookit/color v1.2.5/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg= github.com/gookit/color v1.3.1/go.mod h1:R3ogXq2B9rTbXoSHJ1HyUVAZ3poOJHpd9nQmyGZsfvQ= +github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4 h1:4EZlYQIiyecYJlUbVkFXCXHz1QPhVXcHnQKAzBTPfQo= +github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4/go.mod h1:lEO7XoHJ/xNRBCxrn4h/CEB67h0kW1B0t4ooP2yrjUA= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/goreleaser/chglog v0.1.1/go.mod h1:xSDa/73C0TxBcLvoT2JHh47QyXpCx5rrNVzJKyeFGPw= @@ -548,6 +585,7 @@ github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= @@ -566,6 +604,7 @@ github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoP github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= @@ -573,6 +612,7 @@ github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrj github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-retryablehttp v0.5.1/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.6.8 h1:92lWxgpa+fF3FozM4B3UZtHZMJX8T5XT+TFdCxsPyWs= @@ -598,8 +638,11 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J github.com/heketi/heketi v9.0.1-0.20190917153846-c2e2a4ab7ab9+incompatible/go.mod h1:bB9ly3RchcQqsQ9CpyaQwvva7RS5ytVoSoholZQON6o= github.com/heketi/tests v0.0.0-20151005000721-f3775cbcefd6/go.mod h1:xGMAM8JLi7UkZt1i4FQeQy0R2T8GLUwQhOP5M1gBhy4= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= +github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -613,6 +656,7 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/ishidawataru/sctp v0.0.0-20190723014705-7c296d48a2b5/go.mod h1:DM4VvS+hD/kDi1U1QsX2fnZowwBhqD0Dk3bRPKF/Oc8= github.com/jarcoal/httpmock v1.0.6/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= +github.com/jaytaylor/html2text v0.0.0-20190408195923-01ec452cbe43/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8= @@ -640,6 +684,9 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= +github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= +github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= +github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= @@ -693,10 +740,13 @@ github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1 github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5/go.mod h1:c2mYKRyMb1BPkO5St0c/ps62L4S0W2NAkaTXj9qEI+0= +github.com/lusis/slack-test v0.0.0-20190426140909-c40012f20018/go.mod h1:sFlOUpQL1YcjhFVXhg1CG8ZASEs/Mf1oVb6H75JL/zg= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mailgun/mailgun-go v2.0.0+incompatible/go.mod h1:NWTyU+O4aczg/nsGhQnvHL6v2n5Gy6Sv5tNDVvC6FbU= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -749,6 +799,7 @@ github.com/minio/minio-go/v7 v7.0.2/go.mod h1:dJ80Mv2HeGkYLH1sqS/ksz07ON6csH3S6J github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -764,6 +815,7 @@ github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/ipvs v1.0.1/go.mod h1:2pngiyseZbIKXNv7hsKj3O9UEz30c53MT9005gt2hxQ= github.com/moby/sys/mountinfo v0.1.3/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o= @@ -778,6 +830,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= @@ -806,12 +859,14 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA github.com/nishanths/exhaustive v0.0.0-20200708172631-8866003e3856/go.mod h1:wBEpHwM2OdmeNpdCvRPUlkEbBuaFmcK4Wv8Q7FuGW3c= github.com/nishanths/exhaustive v0.0.0-20200811152831-6cf413ae40e0/go.mod h1:wBEpHwM2OdmeNpdCvRPUlkEbBuaFmcK4Wv8Q7FuGW3c= github.com/nishanths/exhaustive v0.1.0/go.mod h1:S1j9110vxV1ECdCudXRkeMnFQ/DQk9ajLT0Uf2MYZQQ= +github.com/nlopes/slack v0.5.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852/go.mod h1:eqOVx5Vwu4gd2mmMZvVZsgIqNSaW3xxRThUJ0k/TPk4= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -849,6 +904,8 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/opsgenie/opsgenie-go-sdk-v2 v1.0.5 h1:AnS8ZCC5dle8P4X4FZ+IOlX9v0jAkCMiZDIzRnYwBbs= +github.com/opsgenie/opsgenie-go-sdk-v2 v1.0.5/go.mod h1:f0ezb0R/mrB9Hpm5RrIS6EX3ydjsR2nAB88nYYXZcNY= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= @@ -923,6 +980,7 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/robfig/cron v1.1.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -960,16 +1018,21 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/slack-go/slack v0.6.6 h1:ln0fO794CudStSJEfhZ08Ok5JanMjvW6/k2xBuHqedU= +github.com/slack-go/slack v0.6.6/go.mod h1:FGqNzJBmxIsZURAxh2a8D21AnOVvvXZvGligs4npPUM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sony/sonyflake v1.0.0 h1:MpU6Ro7tfXwgn2l5eluf9xQvQJDROTBImNCfRXn/YeM= +github.com/sony/sonyflake v1.0.0/go.mod h1:Jv3cfhf/UFtolOTTRd3q4Nl6ENqM+KfyZ5PseKfZGF4= github.com/sourcegraph/go-diff v0.5.3/go.mod h1:v9JDtjCE4HHHCZGId75rg8gkKKa98RVjBcBGsVmMmak= github.com/sourcegraph/go-diff v0.6.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= @@ -985,8 +1048,9 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -1000,6 +1064,7 @@ github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/ssgreg/nlreturn/v2 v2.0.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/ssgreg/nlreturn/v2 v2.1.0/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= +github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM= github.com/storageos/go-api v2.2.0+incompatible/go.mod h1:ZrLn+e0ZuF3Y65PNF6dIwbJPZqfmtCXxFm9ckv0agOY= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -1020,6 +1085,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tdakkota/asciicheck v0.0.0-20200416190851-d7f85be797a2/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= +github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= +github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= github.com/tetafro/godot v0.4.8/go.mod h1:/7NLHhv08H1+8DNj0MElpAACw1ajsCuf3TKNQxA5S+0= github.com/tetafro/godot v0.4.9/go.mod h1:/7NLHhv08H1+8DNj0MElpAACw1ajsCuf3TKNQxA5S+0= github.com/thecodeteam/goscaleio v0.1.0/go.mod h1:68sdkZAsK8bvEwBlbQnlLS+xU+hvLYM/iQ8KXej1AwM= @@ -1068,6 +1135,8 @@ github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYp github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= +github.com/whilp/git-urls v0.0.0-20191001220047-6db9661140c0 h1:qqllXPzXh+So+mmANlX/gCJrgo+1kQyshMoQ+NASzm0= +github.com/whilp/git-urls v0.0.0-20191001220047-6db9661140c0/go.mod h1:2rx5KE5FLD0HRfkkpyn8JwbVLBdhgeiOb2D2D9LLKM4= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/xanzy/go-gitlab v0.37.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= github.com/xanzy/go-gitlab v0.39.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= @@ -1107,12 +1176,14 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= gocloud.dev v0.20.0/go.mod h1:+Y/RpSXrJthIOM8uFNzWp6MRu9pFPNFEEZrQMxpkfIc= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1185,6 +1256,7 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190607181551-461777fb6f67/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1209,6 +1281,7 @@ golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= @@ -1315,14 +1388,16 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1415,6 +1490,10 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gomodules.xyz/envconfig v1.3.1-0.20190308184047-426f31af0d45 h1:juzzlx91nWAOsHuOVfXZPMXHtJEKouZvY9bBbwlOeYs= +gomodules.xyz/envconfig v1.3.1-0.20190308184047-426f31af0d45/go.mod h1:41y72mzHT7+jFNgyBpJRrZWuZJcLmLrTpq6iGgOFJMQ= +gomodules.xyz/notify v0.1.0 h1:lN7CAFKIWxaXJXm3F/7KTbgw3lUy9peh6iyjgj1skvA= +gomodules.xyz/notify v0.1.0/go.mod h1:wGy0vLXGpabCg0j9WbjzXf7pM7Khz11FqCLtBbTujP0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= @@ -1516,6 +1595,8 @@ google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/AlecAivazis/survey.v1 v1.8.7/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1526,6 +1607,8 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= +gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -1533,6 +1616,7 @@ gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/kyokomi/emoji.v1 v1.5.1/go.mod h1:N9AZ6hi1jHOPn34PsbpufQZUcKftSD7WgS2pgpmH4Lg= gopkg.in/mcuadros/go-syslog.v2 v2.2.1/go.mod h1:l5LPIyOOyIdQquNg+oU6Z3524YwrcqEm0aKH+5zpt2U= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/src-d/go-billy.v4 v4.2.1/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk= diff --git a/hack/gen-plugin-docs/main.go b/hack/gen-docs/main.go similarity index 86% rename from hack/gen-plugin-docs/main.go rename to hack/gen-docs/main.go index f0396a8ce3..fae499c692 100644 --- a/hack/gen-plugin-docs/main.go +++ b/hack/gen-docs/main.go @@ -2,7 +2,6 @@ package main import ( "bytes" - "errors" "fmt" "io" "io/ioutil" @@ -12,6 +11,8 @@ import ( "sort" "strings" + "github.com/argoproj/notifications-engine/pkg/docs" + "github.com/spf13/cobra" "gopkg.in/yaml.v2" @@ -20,6 +21,25 @@ import ( ) func main() { + generateNotificationsDocs() + generatePluginsDocs() +} + +func generateNotificationsDocs() { + os.RemoveAll("./docs/generated/notification-services") + os.MkdirAll("./docs/generated/notification-services/", 0755) + files, err := docs.CopyServicesDocs("./docs/generated/notification-services/") + if err != nil { + log.Fatal(err) + } + if files != nil { + if e := updateMkDocsNav("Notifications", "Services", files); e != nil { + log.Fatal(e) + } + } +} + +func generatePluginsDocs() { tf, o := options.NewFakeArgoRolloutsOptions() defer tf.Cleanup() cmd := cmd.NewCmdArgoRollouts(o) @@ -30,13 +50,13 @@ func main() { log.Fatal(err) } if files != nil { - if e := updateMkDocsNav(files); e != nil { + if e := updateMkDocsNav("Kubectl Plugin", "Commands", files); e != nil { log.Fatal(e) } } } -func updateMkDocsNav(files []string) error { +func updateMkDocsNav(parent string, child string, files []string) error { trimPrefixes(files, "docs/") sort.Strings(files) data, err := ioutil.ReadFile("mkdocs.yml") @@ -47,23 +67,22 @@ func updateMkDocsNav(files []string) error { if e := yaml.Unmarshal(data, &mkdocs); e != nil { return e } - navitem, _ := findNavItem(mkdocs.Nav, "Kubectl Plugin") + navitem, _ := findNavItem(mkdocs.Nav, parent) if navitem == nil { - return errors.New("Can't find 'Kubectl Plugin' nav item in mkdoc.yml") + return fmt.Errorf("Can't find '%s' nav item in mkdoc.yml", parent) } navitemmap := navitem.(map[interface{}]interface{}) - subnav := navitemmap["Kubectl Plugin"].([]interface{}) - subnav = removeNavItem(subnav, "Commands") + subnav := navitemmap[parent].([]interface{}) + subnav = removeNavItem(subnav, child) commands := make(map[string]interface{}) - commands["Commands"] = files - navitemmap["Kubectl Plugin"] = append(subnav, commands) + commands[child] = files + navitemmap[parent] = append(subnav, commands) newmkdocs, err := yaml.Marshal(mkdocs) if err != nil { return err } - ioutil.WriteFile("mkdocs.yml", newmkdocs, 0644) - return nil + return ioutil.WriteFile("mkdocs.yml", newmkdocs, 0644) } func findNavItem(nav []interface{}, key string) (interface{}, int) { diff --git a/hack/update-manifests.sh b/hack/update-manifests.sh index 54ce12f162..161b149bc5 100755 --- a/hack/update-manifests.sh +++ b/hack/update-manifests.sh @@ -28,3 +28,6 @@ ${kust_cmd} "${SRCROOT}/manifests/namespace-install" >> "${SRCROOT}/manifests/na echo "${AUTOGENMSG}" > "${SRCROOT}/manifests/dashboard-install.yaml" ${kust_cmd} "${SRCROOT}/manifests/dashboard-install" >> "${SRCROOT}/manifests/dashboard-install.yaml" + +echo "${AUTOGENMSG}" > "${SRCROOT}/manifests/notifications-install.yaml" +${kust_cmd} "${SRCROOT}/manifests/notifications" >> "${SRCROOT}/manifests/notifications-install.yaml" diff --git a/manifests/notifications-install.yaml b/manifests/notifications-install.yaml new file mode 100644 index 0000000000..f7d8a4436e --- /dev/null +++ b/manifests/notifications-install.yaml @@ -0,0 +1,133 @@ +# This is an auto-generated file. DO NOT EDIT +apiVersion: v1 +data: + template.rollout-completed: | + message: Rollout {{.rollout.metadata.name}} has been completed. + email: + subject: Rollout {{.rollout.metadata.name}} has been completed. + slack: + attachments: | + [{ + "title": "{{ .rollout.metadata.name}}", + "color": "#18be52", + "fields": [ + { + "title": "Strategy", + "value": "{{if .rollout.spec.strategy.blueGreen}}BlueGreen{{end}}{{if .rollout.spec.strategy.canary}}Canary{{end}}", + "short": true + } + {{range $index, $c := .rollout.spec.template.spec.containers}} + {{if not $index}},{{end}} + {{if $index}},{{end}} + { + "title": "{{$c.name}}", + "value": "{{$c.image}}", + "short": true + } + {{end}} + ] + }] + template.rollout-step-completed: | + message: Rollout {{.rollout.metadata.name}} step number {{ add .rollout.status.currentStepIndex 1}}/{{len .rollout.spec.strategy.canary.steps}} has been completed. + email: + subject: Rollout {{.rollout.metadata.name}} step number {{ add .rollout.status.currentStepIndex 1}}/{{len .rollout.spec.strategy.canary.steps}} has been completed. + slack: + attachments: | + [{ + "title": "{{ .rollout.metadata.name}}", + "color": "#18be52", + "fields": [ + { + "title": "Strategy", + "value": "{{if .rollout.spec.strategy.blueGreen}}BlueGreen{{end}}{{if .rollout.spec.strategy.canary}}Canary{{end}}", + "short": true + }, + { + "title": "Step completed", + "value": "{{add .rollout.status.currentStepIndex 1}}/{{len .rollout.spec.strategy.canary.steps}}", + "short": true + } + {{range $index, $c := .rollout.spec.template.spec.containers}} + {{if not $index}},{{end}} + {{if $index}},{{end}} + { + "title": "{{$c.name}}", + "value": "{{$c.image}}", + "short": true + } + {{end}} + ] + }] + template.rollout-updated: | + message: Rollout {{.rollout.metadata.name}} has been updated. + email: + subject: Rollout {{.rollout.metadata.name}} has been updated. + slack: + attachments: | + [{ + "title": "{{ .rollout.metadata.name}}", + "color": "#18be52", + "fields": [ + { + "title": "Strategy", + "value": "{{if .rollout.spec.strategy.blueGreen}}BlueGreen{{end}}{{if .rollout.spec.strategy.canary}}Canary{{end}}", + "short": true + } + {{range $index, $c := .rollout.spec.template.spec.containers}} + {{if not $index}},{{end}} + {{if $index}},{{end}} + { + "title": "{{$c.name}}", + "value": "{{$c.image}}", + "short": true + } + {{end}} + ] + }] + template.scaling-replicaset: | + message: Scaling Rollout {{.rollout.metadata.name}}'s replicaset to {{.rollout.spec.replicas}}. + email: + subject: Scaling Rollout {{.rollout.metadata.name}}'s replcaset to {{.rollout.spec.replicas}}. + slack: + attachments: | + [{ + "title": "{{ .rollout.metadata.name}}", + "color": "#18be52", + "fields": [ + { + "title": "Strategy", + "value": "{{if .rollout.spec.strategy.blueGreen}}BlueGreen{{end}}{{if .rollout.spec.strategy.canary}}Canary{{end}}", + "short": true + }, + { + "title": "Desired replica", + "value": "{{.rollout.spec.replicas}}", + "short": true + }, + { + "title": "Updated replicas", + "value": "{{.rollout.status.updatedReplicas}}", + "short": true + } + {{range $index, $c := .rollout.spec.template.spec.containers}} + {{if not $index}},{{end}} + {{if $index}},{{end}} + { + "title": "{{$c.name}}", + "value": "{{$c.image}}", + "short": true + } + {{end}} + ] + }] + trigger.on-rollout-completed: | + - send: [rollout-completed] + trigger.on-rollout-step-completed: | + - send: [rollout-step-completed] + trigger.on-rollout-updated: | + - send: [rollout-updated] + trigger.on-scaling-replica-set: | + - send: [scaling-replicaset] +kind: ConfigMap +metadata: + name: argo-rollouts-notification-configmap diff --git a/manifests/notifications/argo-rollouts-notification-configmap.yaml b/manifests/notifications/argo-rollouts-notification-configmap.yaml new file mode 100644 index 0000000000..5bbd0f7dd3 --- /dev/null +++ b/manifests/notifications/argo-rollouts-notification-configmap.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: argo-rollouts-notification-configmap \ No newline at end of file diff --git a/manifests/notifications/kustomization.yaml b/manifests/notifications/kustomization.yaml new file mode 100644 index 0000000000..d63cbca662 --- /dev/null +++ b/manifests/notifications/kustomization.yaml @@ -0,0 +1,11 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- argo-rollouts-notification-configmap.yaml + +patchesStrategicMerge: + - on-rollout-completed.yaml + - on-scaling-replica-set.yaml + - on-rollout-step-completed.yaml + - on-rollout-updated.yaml \ No newline at end of file diff --git a/manifests/notifications/on-rollout-completed.yaml b/manifests/notifications/on-rollout-completed.yaml new file mode 100644 index 0000000000..8b62003bfd --- /dev/null +++ b/manifests/notifications/on-rollout-completed.yaml @@ -0,0 +1,33 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: argo-rollouts-notification-configmap +data: + trigger.on-rollout-completed: | + - send: [rollout-completed] + template.rollout-completed: | + message: Rollout {{.rollout.metadata.name}} has been completed. + email: + subject: Rollout {{.rollout.metadata.name}} has been completed. + slack: + attachments: | + [{ + "title": "{{ .rollout.metadata.name}}", + "color": "#18be52", + "fields": [ + { + "title": "Strategy", + "value": "{{if .rollout.spec.strategy.blueGreen}}BlueGreen{{end}}{{if .rollout.spec.strategy.canary}}Canary{{end}}", + "short": true + } + {{range $index, $c := .rollout.spec.template.spec.containers}} + {{if not $index}},{{end}} + {{if $index}},{{end}} + { + "title": "{{$c.name}}", + "value": "{{$c.image}}", + "short": true + } + {{end}} + ] + }] diff --git a/manifests/notifications/on-rollout-step-completed.yaml b/manifests/notifications/on-rollout-step-completed.yaml new file mode 100644 index 0000000000..807364ae94 --- /dev/null +++ b/manifests/notifications/on-rollout-step-completed.yaml @@ -0,0 +1,38 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: argo-rollouts-notification-configmap +data: + trigger.on-rollout-step-completed: | + - send: [rollout-step-completed] + template.rollout-step-completed: | + message: Rollout {{.rollout.metadata.name}} step number {{ add .rollout.status.currentStepIndex 1}}/{{len .rollout.spec.strategy.canary.steps}} has been completed. + email: + subject: Rollout {{.rollout.metadata.name}} step number {{ add .rollout.status.currentStepIndex 1}}/{{len .rollout.spec.strategy.canary.steps}} has been completed. + slack: + attachments: | + [{ + "title": "{{ .rollout.metadata.name}}", + "color": "#18be52", + "fields": [ + { + "title": "Strategy", + "value": "{{if .rollout.spec.strategy.blueGreen}}BlueGreen{{end}}{{if .rollout.spec.strategy.canary}}Canary{{end}}", + "short": true + }, + { + "title": "Step completed", + "value": "{{add .rollout.status.currentStepIndex 1}}/{{len .rollout.spec.strategy.canary.steps}}", + "short": true + } + {{range $index, $c := .rollout.spec.template.spec.containers}} + {{if not $index}},{{end}} + {{if $index}},{{end}} + { + "title": "{{$c.name}}", + "value": "{{$c.image}}", + "short": true + } + {{end}} + ] + }] diff --git a/manifests/notifications/on-rollout-updated.yaml b/manifests/notifications/on-rollout-updated.yaml new file mode 100644 index 0000000000..1e8fee7a56 --- /dev/null +++ b/manifests/notifications/on-rollout-updated.yaml @@ -0,0 +1,33 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: argo-rollouts-notification-configmap +data: + trigger.on-rollout-updated: | + - send: [rollout-updated] + template.rollout-updated: | + message: Rollout {{.rollout.metadata.name}} has been updated. + email: + subject: Rollout {{.rollout.metadata.name}} has been updated. + slack: + attachments: | + [{ + "title": "{{ .rollout.metadata.name}}", + "color": "#18be52", + "fields": [ + { + "title": "Strategy", + "value": "{{if .rollout.spec.strategy.blueGreen}}BlueGreen{{end}}{{if .rollout.spec.strategy.canary}}Canary{{end}}", + "short": true + } + {{range $index, $c := .rollout.spec.template.spec.containers}} + {{if not $index}},{{end}} + {{if $index}},{{end}} + { + "title": "{{$c.name}}", + "value": "{{$c.image}}", + "short": true + } + {{end}} + ] + }] diff --git a/manifests/notifications/on-scaling-replica-set.yaml b/manifests/notifications/on-scaling-replica-set.yaml new file mode 100644 index 0000000000..eabfe5b802 --- /dev/null +++ b/manifests/notifications/on-scaling-replica-set.yaml @@ -0,0 +1,43 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: argo-rollouts-notification-configmap +data: + trigger.on-scaling-replica-set: | + - send: [scaling-replicaset] + template.scaling-replicaset: | + message: Scaling Rollout {{.rollout.metadata.name}}'s replicaset to {{.rollout.spec.replicas}}. + email: + subject: Scaling Rollout {{.rollout.metadata.name}}'s replcaset to {{.rollout.spec.replicas}}. + slack: + attachments: | + [{ + "title": "{{ .rollout.metadata.name}}", + "color": "#18be52", + "fields": [ + { + "title": "Strategy", + "value": "{{if .rollout.spec.strategy.blueGreen}}BlueGreen{{end}}{{if .rollout.spec.strategy.canary}}Canary{{end}}", + "short": true + }, + { + "title": "Desired replica", + "value": "{{.rollout.spec.replicas}}", + "short": true + }, + { + "title": "Updated replicas", + "value": "{{.rollout.status.updatedReplicas}}", + "short": true + } + {{range $index, $c := .rollout.spec.template.spec.containers}} + {{if not $index}},{{end}} + {{if $index}},{{end}} + { + "title": "{{$c.name}}", + "value": "{{$c.image}}", + "short": true + } + {{end}} + ] + }] diff --git a/mkdocs.yml b/mkdocs.yml index 7fb2fa7ccd..82b9a0d7ef 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -8,16 +8,16 @@ theme: palette: primary: teal google_analytics: - - UA-105170809-3 - - auto +- UA-105170809-3 +- auto markdown_extensions: - - codehilite - - admonition - - pymdownx.superfences - - pymdownx.tabbed - - footnotes - - toc: - permalink: true +- codehilite +- admonition +- pymdownx.superfences +- pymdownx.tabbed +- footnotes +- toc: + permalink: true nav: - Overview: index.md - Installation: installation.md @@ -60,6 +60,20 @@ nav: - Web: analysis/web.md - Kayenta: analysis/kayenta.md - Experiments: features/experiment.md +- Notifications: + - Overview: features/notifications.md + - Services: + - generated/notification-services/email.md + - generated/notification-services/github.md + - generated/notification-services/grafana.md + - generated/notification-services/mattermost.md + - generated/notification-services/opsgenie.md + - generated/notification-services/overview.md + - generated/notification-services/rocketchat.md + - generated/notification-services/slack.md + - generated/notification-services/teams.md + - generated/notification-services/telegram.md + - generated/notification-services/webhook.md - Kubectl Plugin: - Overview: features/kubectl-plugin.md - Commands: @@ -75,6 +89,13 @@ nav: - generated/kubectl-argo-rollouts/kubectl-argo-rollouts_list.md - generated/kubectl-argo-rollouts/kubectl-argo-rollouts_list_experiments.md - generated/kubectl-argo-rollouts/kubectl-argo-rollouts_list_rollouts.md + - generated/kubectl-argo-rollouts/kubectl-argo-rollouts_notifications.md + - generated/kubectl-argo-rollouts/kubectl-argo-rollouts_notifications_template.md + - generated/kubectl-argo-rollouts/kubectl-argo-rollouts_notifications_template_get.md + - generated/kubectl-argo-rollouts/kubectl-argo-rollouts_notifications_template_notify.md + - generated/kubectl-argo-rollouts/kubectl-argo-rollouts_notifications_trigger.md + - generated/kubectl-argo-rollouts/kubectl-argo-rollouts_notifications_trigger_get.md + - generated/kubectl-argo-rollouts/kubectl-argo-rollouts_notifications_trigger_run.md - generated/kubectl-argo-rollouts/kubectl-argo-rollouts_pause.md - generated/kubectl-argo-rollouts/kubectl-argo-rollouts_promote.md - generated/kubectl-argo-rollouts/kubectl-argo-rollouts_restart.md diff --git a/pkg/kubectl-argo-rollouts/cmd/cmd.go b/pkg/kubectl-argo-rollouts/cmd/cmd.go index d9597bafd1..1f5cdb6090 100644 --- a/pkg/kubectl-argo-rollouts/cmd/cmd.go +++ b/pkg/kubectl-argo-rollouts/cmd/cmd.go @@ -1,8 +1,7 @@ package cmd import ( - "github.com/spf13/cobra" - + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" "github.com/argoproj/argo-rollouts/pkg/kubectl-argo-rollouts/cmd/abort" "github.com/argoproj/argo-rollouts/pkg/kubectl-argo-rollouts/cmd/create" "github.com/argoproj/argo-rollouts/pkg/kubectl-argo-rollouts/cmd/dashboard" @@ -19,6 +18,10 @@ import ( "github.com/argoproj/argo-rollouts/pkg/kubectl-argo-rollouts/cmd/undo" "github.com/argoproj/argo-rollouts/pkg/kubectl-argo-rollouts/cmd/version" "github.com/argoproj/argo-rollouts/pkg/kubectl-argo-rollouts/options" + "github.com/argoproj/argo-rollouts/utils/record" + notificationcmd "github.com/argoproj/notifications-engine/pkg/cmd" + + "github.com/spf13/cobra" ) const ( @@ -68,5 +71,6 @@ func NewCmdArgoRollouts(o *options.ArgoRolloutsOptions) *cobra.Command { cmd.AddCommand(undo.NewCmdUndo(o)) cmd.AddCommand(dashboard.NewCmdDashboard(o)) cmd.AddCommand(status.NewCmdStatus(o)) + cmd.AddCommand(notificationcmd.NewToolsCommand("notifications", "kubectl argo rollouts notifications", v1alpha1.RolloutGVR, record.NewAPIFactorySettings())) return cmd } diff --git a/utils/record/record.go b/utils/record/record.go index 7e7b897b21..af2db91882 100644 --- a/utils/record/record.go +++ b/utils/record/record.go @@ -1,9 +1,18 @@ package record import ( + "encoding/json" + "regexp" + "strings" + + "github.com/argoproj/notifications-engine/pkg/services" + + "github.com/argoproj/notifications-engine/pkg/api" + "github.com/argoproj/notifications-engine/pkg/subscriptions" "github.com/prometheus/client_golang/prometheus" log "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/kubernetes" @@ -22,7 +31,11 @@ func init() { utilruntime.Must(rolloutscheme.AddToScheme(scheme.Scheme)) } -const controllerAgentName = "rollouts-controller" +const ( + controllerAgentName = "rollouts-controller" + NotificationConfigMap = "argo-rollouts-notification-configmap" + NotificationSecret = "argo-rollouts-notification-secret" +) type EventOptions struct { // EventType is the kubernetes event type (Normal or Warning). Defaults to Normal @@ -48,9 +61,11 @@ type EventRecorderAdapter struct { RolloutEventCounter *prometheus.CounterVec eventf func(object runtime.Object, warn bool, opts EventOptions, messageFmt string, args ...interface{}) + // apiFactory is a notifications engine API factory + apiFactory api.Factory } -func NewEventRecorder(kubeclientset kubernetes.Interface, rolloutEventCounter *prometheus.CounterVec) EventRecorder { +func NewEventRecorder(kubeclientset kubernetes.Interface, rolloutEventCounter *prometheus.CounterVec, apiFactory api.Factory) EventRecorder { // Create event broadcaster // Add argo-rollouts custom resources to the default Kubernetes Scheme so Events can be // logged for argo-rollouts types. @@ -61,6 +76,7 @@ func NewEventRecorder(kubeclientset kubernetes.Interface, rolloutEventCounter *p recorder := &EventRecorderAdapter{ Recorder: k8srecorder, RolloutEventCounter: rolloutEventCounter, + apiFactory: apiFactory, } recorder.eventf = recorder.defaultEventf return recorder @@ -82,6 +98,7 @@ func NewFakeEventRecorder() *FakeEventRecorder { }, []string{"name", "namespace", "type", "reason"}, ), + nil, ).(*EventRecorderAdapter) recorder.Recorder = record.NewFakeRecorder(1000) fakeRecorder := &FakeEventRecorder{} @@ -119,6 +136,10 @@ func (e *EventRecorderAdapter) defaultEventf(object runtime.Object, warn bool, o if kind == "Rollout" { e.RolloutEventCounter.WithLabelValues(namespace, name, opts.EventType, opts.EventReason).Inc() } + err := e.sendNotifications(object, opts) + if err != nil { + logCtx.Errorf("Notifications failed to send for eventReason %s with error: %s", opts.EventReason, err) + } } logFn := logCtx.Infof @@ -131,3 +152,65 @@ func (e *EventRecorderAdapter) defaultEventf(object runtime.Object, warn bool, o func (e *EventRecorderAdapter) K8sRecorder() record.EventRecorder { return e.Recorder } + +func NewAPIFactorySettings() api.Settings { + return api.Settings{ + SecretName: NotificationSecret, + ConfigMapName: NotificationConfigMap, + InitGetVars: func(cfg *api.Config, configMap *corev1.ConfigMap, secret *corev1.Secret) (api.GetVars, error) { + return func(obj map[string]interface{}, dest services.Destination) map[string]interface{} { + return map[string]interface{}{"rollout": obj} + }, nil + }, + } +} + +// Send notifications for triggered event if user is subscribed +func (e *EventRecorderAdapter) sendNotifications(object runtime.Object, opts EventOptions) error { + subsFromAnnotations := subscriptions.Annotations(object.(metav1.Object).GetAnnotations()) + destByTrigger := subsFromAnnotations.GetDestinations(nil, map[string][]string{}) + + trigger := translateReasonToTrigger(opts.EventReason) + + destinations := destByTrigger[trigger] + if len(destinations) == 0 { + return nil + } + + notificationsAPI, err := e.apiFactory.GetAPI() + if err != nil { + return err + } + + // Creates config for notifications for built-in triggers + triggerActions, ok := notificationsAPI.GetConfig().Triggers[trigger] + if !ok { + return nil + } + + objBytes, err := json.Marshal(object) + if err != nil { + return err + } + var objMap map[string]interface{} + err = json.Unmarshal(objBytes, &objMap) + if err != nil { + return err + } + for _, dest := range destinations { + err = notificationsAPI.Send(objMap, triggerActions[0].Send, dest) + if err != nil { + log.Errorf("notification error: %s", err.Error()) + return err + } + } + return nil +} + +func translateReasonToTrigger(reason string) string { + var matchFirstCap = regexp.MustCompile("(.)([A-Z][a-z]+)") + var matchAllCap = regexp.MustCompile("([a-z0-9])([A-Z])") + trigger := matchFirstCap.ReplaceAllString(reason, "${1}-${2}") + trigger = matchAllCap.ReplaceAllString(trigger, "${1}-${2}") + return "on-" + strings.ToLower(trigger) +} diff --git a/utils/record/record_test.go b/utils/record/record_test.go index 8054868827..15b89f83dd 100644 --- a/utils/record/record_test.go +++ b/utils/record/record_test.go @@ -2,10 +2,16 @@ package record import ( "bytes" + "errors" "fmt" "strings" "testing" + "github.com/argoproj/notifications-engine/pkg/api" + "github.com/argoproj/notifications-engine/pkg/mocks" + "github.com/argoproj/notifications-engine/pkg/services" + "github.com/argoproj/notifications-engine/pkg/triggers" + "github.com/golang/mock/gomock" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" log "github.com/sirupsen/logrus" @@ -75,3 +81,93 @@ func TestIncCounter(t *testing.T) { assert.Equal(t, float64(3), *buf.Counter.Value) assert.Equal(t, []string{"FooReason", "FooReason", "FooReason"}, rec.Events) } + +func TestSendNotifications(t *testing.T) { + r := v1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Name: "guestbook", + Namespace: "default", + Annotations: map[string]string{"notifications.argoproj.io/subscribe.on-foo-reason.console": "console"}, + }, + } + mockCtrl := gomock.NewController(t) + mockAPI := mocks.NewMockAPI(mockCtrl) + mockAPI.EXPECT().Send(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockAPI.EXPECT().GetConfig().Return(api.Config{ + Triggers: map[string][]triggers.Condition{"on-foo-reason": {triggers.Condition{Send: []string{"my-template"}}}}}).AnyTimes() + apiFactory := &mocks.FakeFactory{Api: mockAPI} + rec := NewFakeEventRecorder() + rec.EventRecorderAdapter.apiFactory = apiFactory + + err := rec.sendNotifications(&r, EventOptions{EventReason: "FooReason"}) + assert.NoError(t, err) +} + +func TestSendNotificationsFails(t *testing.T) { + r := v1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Name: "guestbook", + Namespace: "default", + Annotations: map[string]string{"notifications.argoproj.io/subscribe.on-foo-reason.console": "console"}, + }, + } + + t.Run("SendError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + mockAPI := mocks.NewMockAPI(mockCtrl) + mockAPI.EXPECT().Send(gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to send")).AnyTimes() + mockAPI.EXPECT().GetConfig().Return(api.Config{ + Triggers: map[string][]triggers.Condition{"on-foo-reason": {triggers.Condition{Send: []string{"my-template"}}}}}).AnyTimes() + apiFactory := &mocks.FakeFactory{Api: mockAPI} + rec := NewFakeEventRecorder() + rec.EventRecorderAdapter.apiFactory = apiFactory + + err := rec.sendNotifications(&r, EventOptions{EventReason: "FooReason"}) + assert.Error(t, err) + }) + + t.Run("GetAPIError", func(t *testing.T) { + apiFactory := &mocks.FakeFactory{Err: errors.New("failed to get API")} + rec := NewFakeEventRecorder() + rec.EventRecorderAdapter.apiFactory = apiFactory + + err := rec.sendNotifications(&r, EventOptions{EventReason: "FooReason"}) + assert.Error(t, err) + }) + +} + +func TestSendNotificationsNoTrigger(t *testing.T) { + r := v1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Name: "guestbook", + Namespace: "default", + Annotations: map[string]string{"notifications.argoproj.io/subscribe.on-missing-reason.console": "console"}, + }, + } + + mockCtrl := gomock.NewController(t) + mockAPI := mocks.NewMockAPI(mockCtrl) + mockAPI.EXPECT().GetConfig().Return(api.Config{ + Triggers: map[string][]triggers.Condition{"on-foo-reason": {triggers.Condition{Send: []string{"my-template"}}}}}).AnyTimes() + mockAPI.EXPECT().Send(gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("failed to send")).Times(0) + apiFactory := &mocks.FakeFactory{Api: mockAPI} + rec := NewFakeEventRecorder() + rec.EventRecorderAdapter.apiFactory = apiFactory + + err := rec.sendNotifications(&r, EventOptions{EventReason: "MissingReason"}) + assert.NoError(t, err) +} + +func TestNewAPIFactorySettings(t *testing.T) { + settings := NewAPIFactorySettings() + assert.Equal(t, NotificationConfigMap, settings.ConfigMapName) + assert.Equal(t, NotificationSecret, settings.SecretName) + getVars, err := settings.InitGetVars(nil, nil, nil) + assert.NoError(t, err) + + rollout := map[string]interface{}{"name": "hello"} + vars := getVars(rollout, services.Destination{}) + + assert.Equal(t, map[string]interface{}{"rollout": rollout}, vars) +}