diff --git a/builtin/templates_test.go b/builtin/templates_test.go
index dad6a5a4..7d852553 100644
--- a/builtin/templates_test.go
+++ b/builtin/templates_test.go
@@ -15,7 +15,7 @@ func triggerWithTemplate(name string) (triggers.Trigger, error) {
Name: "test",
Template: name,
Condition: "true",
- }})
+ }}, nil)
if err != nil {
return nil, err
}
diff --git a/builtin/triggers_test.go b/builtin/triggers_test.go
index fdc83ccb..52bfbd3d 100644
--- a/builtin/triggers_test.go
+++ b/builtin/triggers_test.go
@@ -51,7 +51,7 @@ func TestBuiltInTriggers(t *testing.T) {
if testCase, ok := testCases[trigger.Name]; !ok {
t.Fatalf("No tests for trigger %s", trigger.Name)
} else {
- builtInTriggers, err := triggers.GetTriggers(Templates, []triggers.NotificationTrigger{trigger})
+ builtInTriggers, err := triggers.GetTriggers(Templates, []triggers.NotificationTrigger{trigger}, nil)
assert.NoError(t, err)
item := builtInTriggers[trigger.Name]
for i := range testCase.negativeInputs {
diff --git a/cmd/controller.go b/cmd/controller.go
index 9cb04c21..9bebebf4 100644
--- a/cmd/controller.go
+++ b/cmd/controller.go
@@ -11,6 +11,7 @@ import (
"github.com/argoproj-labs/argocd-notifications/builtin"
"github.com/argoproj-labs/argocd-notifications/controller"
"github.com/argoproj-labs/argocd-notifications/notifiers"
+ "github.com/argoproj-labs/argocd-notifications/shared/argocd"
"github.com/argoproj-labs/argocd-notifications/shared/cmd"
"github.com/argoproj-labs/argocd-notifications/shared/settings"
"github.com/argoproj-labs/argocd-notifications/triggers"
@@ -52,6 +53,7 @@ func newControllerCommand() *cobra.Command {
appLabelSelector string
logLevel string
metricsPort int
+ argocdRepoServer string
)
var command = cobra.Command{
Use: "controller",
@@ -80,6 +82,12 @@ func newControllerCommand() *cobra.Command {
}
log.SetLevel(level)
+ argocdService, err := argocd.NewArgoCDService(k8sClient, namespace, argocdRepoServer)
+ if err != nil {
+ return err
+ }
+ defer argocdService.Close()
+
registry := controller.NewMetricsRegistry()
http.Handle("/metrics", promhttp.HandlerFor(prometheus.Gatherers{registry, prometheus.DefaultGatherer}, promhttp.HandlerOpts{}))
@@ -90,7 +98,7 @@ func newControllerCommand() *cobra.Command {
log.Infof("loading configuration %d", metricsPort)
var cancelPrev context.CancelFunc
- watchConfig(context.Background(), k8sClient, namespace, func(triggers map[string]triggers.Trigger, notifiers map[string]notifiers.Notifier, cfg *settings.Config) error {
+ watchConfig(context.Background(), argocdService, k8sClient, namespace, func(triggers map[string]triggers.Trigger, notifiers map[string]notifiers.Notifier, cfg *settings.Config) error {
if cancelPrev != nil {
log.Info("Settings had been updated. Restarting controller...")
cancelPrev()
@@ -121,10 +129,11 @@ func newControllerCommand() *cobra.Command {
command.Flags().StringVar(&namespace, "namespace", "", "Namespace which controller handles. Current namespace if empty.")
command.Flags().StringVar(&logLevel, "loglevel", "info", "Set the logging level. One of: debug|info|warn|error")
command.Flags().IntVar(&metricsPort, "metrics-port", defaultMetricsPort, "Metrics port")
+ command.Flags().StringVar(&argocdRepoServer, "argocd-repo-server", "argocd-repo-server:8081", "Argo CD repo server address")
return &command
}
-func watchConfig(ctx context.Context, clientset kubernetes.Interface, namespace string, callback func(map[string]triggers.Trigger, map[string]notifiers.Notifier, *settings.Config) error) {
+func watchConfig(ctx context.Context, argocdService argocd.Service, clientset kubernetes.Interface, namespace string, callback func(map[string]triggers.Trigger, map[string]notifiers.Notifier, *settings.Config) error) {
var secret *v1.Secret
var configMap *v1.ConfigMap
lock := &sync.Mutex{}
@@ -138,7 +147,7 @@ func watchConfig(ctx context.Context, clientset kubernetes.Interface, namespace
configMap = newConfigMap
}
if secret != nil && configMap != nil {
- if t, n, c, err := settings.ParseConfig(configMap, secret, defaultCfg); err == nil {
+ if t, n, c, err := settings.ParseConfig(configMap, secret, defaultCfg, argocdService); err == nil {
if err = callback(t, n, c); err != nil {
log.Fatalf("Failed to start controller: %v", err)
}
diff --git a/cmd/controller_test.go b/cmd/controller_test.go
index 5287c352..20dd7071 100644
--- a/cmd/controller_test.go
+++ b/cmd/controller_test.go
@@ -4,17 +4,22 @@ import (
"context"
"testing"
+ "github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
"github.com/argoproj-labs/argocd-notifications/notifiers"
+ "github.com/argoproj-labs/argocd-notifications/shared/argocd/mocks"
"github.com/argoproj-labs/argocd-notifications/shared/settings"
"github.com/argoproj-labs/argocd-notifications/triggers"
)
func TestWatchConfig(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
configMap := &v1.ConfigMap{
@@ -46,8 +51,9 @@ templates:
triggersMap := make(map[string]triggers.Trigger)
notifiersMap := make(map[string]notifiers.Notifier)
+ argocdService := mocks.NewMockService(ctrl)
clientset := fake.NewSimpleClientset(configMap, secret)
- watchConfig(ctx, clientset, "default", func(t map[string]triggers.Trigger, n map[string]notifiers.Notifier, cfg *settings.Config) error {
+ watchConfig(ctx, argocdService, clientset, "default", func(t map[string]triggers.Trigger, n map[string]notifiers.Notifier, cfg *settings.Config) error {
triggersMap = t
notifiersMap = n
return nil
diff --git a/cmd/tools/context.go b/cmd/tools/context.go
index ff7ab81a..0db2341c 100644
--- a/cmd/tools/context.go
+++ b/cmd/tools/context.go
@@ -1,9 +1,11 @@
package tools
import (
+ "context"
"io"
"io/ioutil"
"path/filepath"
+ "sync"
"github.com/ghodss/yaml"
v1 "k8s.io/api/core/v1"
@@ -14,18 +16,54 @@ import (
"k8s.io/client-go/tools/clientcmd"
"github.com/argoproj-labs/argocd-notifications/notifiers"
+ "github.com/argoproj-labs/argocd-notifications/shared/argocd"
"github.com/argoproj-labs/argocd-notifications/shared/clients"
"github.com/argoproj-labs/argocd-notifications/shared/settings"
"github.com/argoproj-labs/argocd-notifications/triggers"
+ "github.com/argoproj-labs/argocd-notifications/triggers/expr/shared"
)
+type clientsSource = func() (kubernetes.Interface, dynamic.Interface, string, error)
+
type commandContext struct {
configMapPath string
secretPath string
defaultCfg settings.Config
stdout io.Writer
stderr io.Writer
- getK8SClients func() (kubernetes.Interface, dynamic.Interface, string, error)
+ getK8SClients clientsSource
+ argocdService *lazyArgocdServiceInitializer
+}
+
+type lazyArgocdServiceInitializer struct {
+ argocdRepoServer *string
+ argocdService argocd.Service
+ init sync.Once
+ getK8SClients clientsSource
+}
+
+func (svc *lazyArgocdServiceInitializer) initArgoCDService() error {
+ k8sClient, _, ns, err := svc.getK8SClients()
+ if err != nil {
+ return err
+ }
+ argocdService, err := argocd.NewArgoCDService(k8sClient, ns, *svc.argocdRepoServer)
+ if err != nil {
+ return err
+ }
+ svc.argocdService = argocdService
+ return nil
+}
+
+func (svc *lazyArgocdServiceInitializer) GetCommitMetadata(ctx context.Context, repoURL string, commitSHA string) (*shared.CommitMetadata, error) {
+ var err error
+ svc.init.Do(func() {
+ err = svc.initArgoCDService()
+ })
+ if err != nil {
+ return nil, err
+ }
+ return svc.argocdService.GetCommitMetadata(ctx, repoURL, commitSHA)
}
func getK8SClients(clientConfig clientcmd.ClientConfig) (kubernetes.Interface, dynamic.Interface, string, error) {
@@ -93,7 +131,7 @@ func (c *commandContext) getConfig() (map[string]triggers.Trigger, map[string]no
}
}
- return settings.ParseConfig(&configMap, &secret, c.defaultCfg)
+ return settings.ParseConfig(&configMap, &secret, c.defaultCfg, &lazyArgocdServiceInitializer{})
}
func (c *commandContext) loadApplication(application string) (*unstructured.Unstructured, error) {
diff --git a/cmd/tools/template.go b/cmd/tools/template.go
index 91ed1cab..640e7924 100644
--- a/cmd/tools/template.go
+++ b/cmd/tools/template.go
@@ -68,7 +68,7 @@ argocd-notifications tools template notify app-sync-succeeded guestbook
Name: "__test__",
Template: name,
Condition: "true",
- }})
+ }}, cmdContext.argocdService)
if err != nil {
_, _ = fmt.Fprintf(cmdContext.stderr, "failed to parse config: %v\n", err)
return nil
@@ -90,7 +90,7 @@ argocd-notifications tools template notify app-sync-succeeded guestbook
notifierType := parts[0]
notifier, ok := notifiersByName[notifierType]
if !ok {
- _, _ = fmt.Fprintf(cmdContext.stderr, "%s is not valid recipient type.", notifierType)
+ _, _ = fmt.Fprintf(cmdContext.stderr, "%s is not valid recipient type.\n", notifierType)
return nil
}
@@ -98,10 +98,12 @@ argocd-notifications tools template notify app-sync-succeeded guestbook
ctx["notificationType"] = notifierType
notification, err := trigger.FormatNotification(app, ctx)
if err != nil {
- _, _ = fmt.Fprintf(cmdContext.stderr, "failed to format notification: %v", err)
+ _, _ = fmt.Fprintf(cmdContext.stderr, "failed to format notification: %v\n", err)
+ return nil
}
if err = notifier.Send(*notification, parts[1]); err != nil {
- _, _ = fmt.Fprintf(cmdContext.stderr, "failed to notify '%s': %v", recipient, err)
+ _, _ = fmt.Fprintf(cmdContext.stderr, "failed to notify '%s': %v\n", recipient, err)
+ return nil
}
}
diff --git a/cmd/tools/tools.go b/cmd/tools/tools.go
index 35cdfe44..992b07bc 100644
--- a/cmd/tools/tools.go
+++ b/cmd/tools/tools.go
@@ -51,10 +51,12 @@ func printFormatted(input interface{}, output string, out io.Writer) error {
func NewToolsCommand(defaultCfg settings.Config) *cobra.Command {
var (
- cmdContext = commandContext{
- defaultCfg: defaultCfg,
- stdout: os.Stdout,
- stderr: os.Stderr,
+ argocdRepoServer string
+ cmdContext = commandContext{
+ defaultCfg: defaultCfg,
+ stdout: os.Stdout,
+ stderr: os.Stderr,
+ argocdService: &lazyArgocdServiceInitializer{argocdRepoServer: &argocdRepoServer},
}
)
var command = cobra.Command{
@@ -72,9 +74,12 @@ func NewToolsCommand(defaultCfg settings.Config) *cobra.Command {
"config-map", "", "argocd-notifications-cm.yaml file path")
command.PersistentFlags().StringVar(&cmdContext.secretPath,
"secret", "", "argocd-notifications-secret.yaml file path. Use empty secret if provided value is ':empty'")
+ command.PersistentFlags().StringVar(&argocdRepoServer,
+ "argocd-repo-server", "argocd-repo-server:8081", "Argo CD repo server address")
clientConfig := cmd.AddK8SFlagsToCmd(&command)
cmdContext.getK8SClients = func() (kubernetes.Interface, dynamic.Interface, string, error) {
return getK8SClients(clientConfig)
}
+ cmdContext.argocdService.getK8SClients = cmdContext.getK8SClients
return &command
}
diff --git a/docs/argocd-notifications-cm.yaml b/docs/argocd-notifications-cm.yaml
index a5ee3f44..150ecd2d 100644
--- a/docs/argocd-notifications-cm.yaml
+++ b/docs/argocd-notifications-cm.yaml
@@ -33,5 +33,6 @@ data:
body: |
Application details: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}.
# Override one field in built-in template
- - name: app-sync-status
+ - name: on-sync-succeeded
title: Application {{.app.metadata.name}} sync status is {{.app.status.sync.status}}
+ body: "{{call .git.GetCommitMetadata .app.status.sync.revision}}"
diff --git a/docs/triggers_and_templates/functions.md b/docs/triggers_and_templates/functions.md
new file mode 100644
index 00000000..515d49ab
--- /dev/null
+++ b/docs/triggers_and_templates/functions.md
@@ -0,0 +1,54 @@
+## Functions
+
+Both templates and triggers have access to the set of functions.
+
+Trigger example:
+
+```yaml
+name: app-operation-stuck
+condition: time.Now().Sub(time.Parse(app.status.operationState.startedAt)).Minutes() >= 5
+template: my-template
+```
+
+Template example:
+```yaml
+name: my-template
+title: Application {{.app.metadata.name}} sync status is {{.app.status.sync.status}}
+body: "Author: {{(call .repo.GetCommitMetadata .app.status.sync.revision).Author}}"
+```
+
+### **time**
+Time related functions.
+
+
+**`time.Now() Time`**
+
+Executes function built-in Golang [time.Now](https://golang.org/pkg/time/#Now) function.
+Returns an instance of Golang [Time](https://golang.org/pkg/time/#Time).
+
+
+**`time.Parse(val string) Time`**
+
+Parses specified string using RFC3339 layout. Returns an instance of Golang [Time](https://golang.org/pkg/time/#Time).
+
+### **repo**
+Functions that provide additional information about Application source repository.
+
+**`repo.RepoURLToHTTPS(url string) string`**
+
+Transforms given GIT URL into HTTPs format.
+
+
+**`repo.FullNameByRepoURL(url string) string`**
+
+Returns repository URL full name `(/)`. Currently supports only Github, Gitlab and Bitbucket.
+
+
+**`repo.GetCommitMetadata(sha string) CommitMetadata`**
+
+Returns commit metadata. The commit must belong to the application source repository. `CommitMetadata` fields:
+
+* `Message string` commit message
+* `Author string` - commit author
+* `Date time.Time` - commit creation date
+* `Tags []string` - Associated tags
diff --git a/docs/triggers_and_templates/index.md b/docs/triggers_and_templates/index.md
index 7f4876a7..81358cb4 100644
--- a/docs/triggers_and_templates/index.md
+++ b/docs/triggers_and_templates/index.md
@@ -27,20 +27,6 @@ evaluation is powered by [antonmedv/expr](https://github.com/antonmedv/expr). Th
at [Language-Definition.md](https://github.com/antonmedv/expr/blob/master/docs/Language-Definition.md).
* **enabled** - flag that indicates if trigger is enabled or not. By default trigger is enabled.
-### Functions
-
-Following functions can be used with-in the condition expression:
-
-**time** (v0.5+)
-
-* `time.Now` - executes function built-in Golang [time.Now](https://golang.org/pkg/time/#Now) function.
-* `time.Parse` - parses specified string using RFC3339 layout
-
-**repo** (v0.6+)
-
-* `repo.RepoURLToHTTPS` - transforms given GIT URL into HTTPs format
-* `repo.FullNameByRepoURL` - returns repository URL full name (/). Currently supports only Github, Gitlab and Bitbucket.
-
## Templates
The notification template is used to generate the notification content. The template is leveraging
@@ -61,3 +47,4 @@ Each template has access to the `app` and `context` fields:
- `app` holds the application object.
- `context` is user defined string map and might include any string keys and values.
+
diff --git a/go.mod b/go.mod
index 4d96a4f0..aca6f86c 100644
--- a/go.mod
+++ b/go.mod
@@ -7,14 +7,20 @@ require (
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible
github.com/antonmedv/expr v1.4.1
+ github.com/argoproj/argo-cd v1.5.4
+ github.com/argoproj/pkg v0.0.0-20200424003221-9b858eff18a1 // indirect
github.com/evanphx/json-patch v4.5.0+incompatible // indirect
github.com/ghodss/yaml v1.0.0
+ github.com/gobwas/glob v0.2.3 // indirect
+ github.com/gogo/protobuf v1.3.1 // indirect
github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7 // indirect
github.com/golang/mock v1.3.1
github.com/googleapis/gnostic v0.3.1 // indirect
+ github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 // indirect
github.com/huandu/xstrings v1.3.0 // indirect
github.com/imdario/mergo v0.3.8 // indirect
github.com/jstemmer/go-junit-report v0.9.1 // indirect
+ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/magiconair/properties v1.8.0
github.com/mitchellh/copystructure v1.0.0 // indirect
@@ -22,17 +28,18 @@ require (
github.com/olekukonko/tablewriter v0.0.4
github.com/opsgenie/opsgenie-go-sdk-v2 v1.0.5
github.com/prometheus/client_golang v1.6.0
+ github.com/robfig/cron v1.2.0 // indirect
github.com/sirupsen/logrus v1.4.2
github.com/spf13/cobra v0.0.5
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.4.0
github.com/whilp/git-urls v0.0.0-20191001220047-6db9661140c0
- golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4 // indirect
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 // indirect
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6 // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
gomodules.xyz/notify v0.1.0
gopkg.in/inf.v0 v0.9.1 // indirect
+ gopkg.in/src-d/go-git.v4 v4.13.1 // indirect
k8s.io/api v0.0.0-20191114100352-16d7abae0d2a
k8s.io/apimachinery v0.0.0-20191028221656-72ed19daf4bb
k8s.io/client-go v0.0.0-20191114101535-6c5935290e33
diff --git a/go.sum b/go.sum
index f38f1e87..eabe69d3 100644
--- a/go.sum
+++ b/go.sum
@@ -18,18 +18,27 @@ github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF0
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/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
+github.com/PuerkitoBio/purell v1.0.0 h1:0GoNN3taZV6QI81IXgCbxMyEaJDXMSIjArYBCYzVVvs=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2 h1:JCHLVE3B+kJde7bIEo5N4J+ZbLhp0J1Fs+ulyRws4gE=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
+github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antlr/antlr4 v0.0.0-20191011202612-ad2bd05285ca h1:QHbltbNkVcw97h4zA/L8gA4o3dJiFvBZ0gyZHrYXHbs=
github.com/antlr/antlr4 v0.0.0-20191011202612-ad2bd05285ca/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y=
github.com/antonmedv/expr v1.4.1 h1:ienOlev0YSJVJbcWwFOVpu2Uxu4OVBMXtp9YGifrxGQ=
github.com/antonmedv/expr v1.4.1/go.mod h1:xesgliOuukGf21740qhh8PvFdN66yZ9lJJ/PzSFAmzI=
github.com/appscode/go v0.0.0-20190808133642-1d4ef1f1c1e0/go.mod h1:iy07dV61Z7QQdCKJCIvUoDL21u6AIceRhZzyleh2ymc=
+github.com/argoproj/argo-cd v1.5.4 h1:44NnPUZrB5TPntrNHqKXhphekTv3WaxSmIFAbg1oy2g=
+github.com/argoproj/argo-cd v1.5.4/go.mod h1:UPOPiF6Y1y/oTL3X1KcuLbu7ljD7f4+SIaXvlowBmhE=
+github.com/argoproj/pkg v0.0.0-20200424003221-9b858eff18a1 h1:BCuMRvKYHPuPN2Gep3uY+XOScGNCBFbF/pXYlhmyJjg=
+github.com/argoproj/pkg v0.0.0-20200424003221-9b858eff18a1/go.mod h1:2EZ44RG/CcgtPTwrRR0apOc7oU6UIw8GjCUJWZ8X3bM=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
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=
@@ -47,6 +56,7 @@ github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8Nz
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
+github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -55,7 +65,10 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
+github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
+github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
+github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
@@ -64,6 +77,7 @@ github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqL
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
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/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
@@ -71,21 +85,31 @@ github.com/gdamore/tcell v1.1.2/go.mod h1:h3kq4HO9l2On+V9ed8w8ewqQEmGCSSHOgQ+2h8
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
+github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1 h1:wSt/4CYxs70xbATrGXhokKF1i0tZjENLOo1ioIO13zk=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
+github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9 h1:tF+augKRWlWx0J0B7ZyyKSiTyV6E1zZe+7b3qQlcEf8=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
+github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501 h1:C1JKChikHGpXwT5UQDFaryIpDtyyGL/CR6C2kB7F1oc=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
+github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87 h1:zP3nY8Tk2E6RTkqGYrarZXuzh+ffyLDljLxCy1iJw80=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
+github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
+github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
+github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7 h1:u4bArs140e9+AfE52mFHOXVFnOSBJBRlzTHrOPLOIhE=
@@ -130,6 +154,8 @@ github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
+github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 h1:0IKlLyQ3Hs9nDaiK5cSHAGmcQEIC8l2Ts1u6x5Dfrqg=
+github.com/grpc-ecosystem/go-grpc-middleware v1.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s=
github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-retryablehttp v0.5.1 h1:Vsx5XKPqPs3M6sM4U4GWyUqFS8aBiL9U5gkgvpkg4SE=
@@ -149,6 +175,9 @@ github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
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 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
+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/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@@ -165,6 +194,11 @@ github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0b
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/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
+github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
+github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
+github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
+github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -174,6 +208,7 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
@@ -182,6 +217,7 @@ github.com/lusis/slack-test v0.0.0-20190426140909-c40012f20018/go.mod h1:sFlOUpQ
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailgun/mailgun-go v2.0.0+incompatible/go.mod h1:NWTyU+O4aczg/nsGhQnvHL6v2n5Gy6Sv5tNDVvC6FbU=
+github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a h1:TpvdAwDAt1K4ANVOfcihouRdvP+MgAfDWwBuct4l6ZY=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@@ -193,6 +229,7 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
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.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
@@ -221,8 +258,10 @@ github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
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/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -248,11 +287,15 @@ github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/rivo/tview v0.0.0-20190515161233-bd836ef13b4b/go.mod h1:+rKjP5+h9HMwWRpAfhIkkQ9KE3m3Nz5rwn7YtUpwgqk=
github.com/rivo/uniseg v0.0.0-20190513083848-b9f5b9457d44/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
+github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sanity-io/litter v1.1.0 h1:BllcKWa3VbZmOZbDCoszYLk7zCsKHz5Beossi8SUcTc=
github.com/sanity-io/litter v1.1.0/go.mod h1:CJ0VCw2q4qKU7LaQr3n7UOSHzgEMgcGco7N/SkZQPjw=
+github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
+github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@@ -270,9 +313,12 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
+github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
+github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -281,17 +327,25 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
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/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
+github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/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-20190308221718-c2843e01d9a2/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-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4 h1:ydJNl0ENAG67pFbB+9tfhiL2pYqLhfoaZFw/cjLhY4A=
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
+golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -307,6 +361,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -330,10 +386,12 @@ golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -347,6 +405,7 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -356,6 +415,7 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/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=
@@ -368,7 +428,11 @@ google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7 h1:ZUjXAXmrAyrmmCPHgCA/vChHcpsX27MZ3yBonD/z1KE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@@ -392,8 +456,15 @@ gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
+gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg=
+gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
+gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
+gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=
+gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
diff --git a/mkdocs.yml b/mkdocs.yml
index 9ab85951..2f7ee73c 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -22,6 +22,7 @@ nav:
- Overview: index.md
- Triggers and Templates:
- triggers_and_templates/index.md
+ - triggers_and_templates/functions.md
- triggers_and_templates/slack.md
- Notification Services:
- services/overview.md
diff --git a/shared/argocd/mocks/service.go b/shared/argocd/mocks/service.go
new file mode 100644
index 00000000..aeb78e55
--- /dev/null
+++ b/shared/argocd/mocks/service.go
@@ -0,0 +1,50 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: github.com/argoproj-labs/argocd-notifications/shared/argocd (interfaces: Service)
+
+// Package mocks is a generated GoMock package.
+package mocks
+
+import (
+ context "context"
+ shared "github.com/argoproj-labs/argocd-notifications/triggers/expr/shared"
+ gomock "github.com/golang/mock/gomock"
+ reflect "reflect"
+)
+
+// MockService is a mock of Service interface
+type MockService struct {
+ ctrl *gomock.Controller
+ recorder *MockServiceMockRecorder
+}
+
+// MockServiceMockRecorder is the mock recorder for MockService
+type MockServiceMockRecorder struct {
+ mock *MockService
+}
+
+// NewMockService creates a new mock instance
+func NewMockService(ctrl *gomock.Controller) *MockService {
+ mock := &MockService{ctrl: ctrl}
+ mock.recorder = &MockServiceMockRecorder{mock}
+ return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use
+func (m *MockService) EXPECT() *MockServiceMockRecorder {
+ return m.recorder
+}
+
+// GetCommitMetadata mocks base method
+func (m *MockService) GetCommitMetadata(arg0 context.Context, arg1, arg2 string) (*shared.CommitMetadata, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetCommitMetadata", arg0, arg1, arg2)
+ ret0, _ := ret[0].(*shared.CommitMetadata)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetCommitMetadata indicates an expected call of GetCommitMetadata
+func (mr *MockServiceMockRecorder) GetCommitMetadata(arg0, arg1, arg2 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCommitMetadata", reflect.TypeOf((*MockService)(nil).GetCommitMetadata), arg0, arg1, arg2)
+}
diff --git a/shared/argocd/service.go b/shared/argocd/service.go
new file mode 100644
index 00000000..904b80bc
--- /dev/null
+++ b/shared/argocd/service.go
@@ -0,0 +1,71 @@
+package argocd
+
+import (
+ "context"
+
+ "github.com/argoproj/argo-cd/reposerver/apiclient"
+ "github.com/argoproj/argo-cd/util/db"
+ "github.com/argoproj/argo-cd/util/settings"
+ log "github.com/sirupsen/logrus"
+ "k8s.io/client-go/kubernetes"
+
+ "github.com/argoproj-labs/argocd-notifications/triggers/expr/shared"
+)
+
+//go:generate mockgen -destination=./mocks/service.go -package=mocks github.com/argoproj-labs/argocd-notifications/shared/argocd Service
+
+type Service interface {
+ GetCommitMetadata(ctx context.Context, repoURL string, commitSHA string) (*shared.CommitMetadata, error)
+}
+
+func NewArgoCDService(clientset kubernetes.Interface, namespace string, repoServerAddress string) (*argoCDService, error) {
+ ctx, cancel := context.WithCancel(context.Background())
+ settingsMgr := settings.NewSettingsManager(ctx, clientset, namespace)
+ repoClientset := apiclient.NewRepoServerClientset(repoServerAddress, 5)
+ closer, repoClient, err := repoClientset.NewRepoServerClient()
+ if err != nil {
+ cancel()
+ return nil, err
+ }
+
+ dispose := func() {
+ cancel()
+ if err := closer.Close(); err != nil {
+ log.Warnf("Failed to close repo server connection: %v", err)
+ }
+ }
+ return &argoCDService{settingsMgr: settingsMgr, namespace: namespace, repoServerClient: repoClient, dispose: dispose}, nil
+}
+
+type argoCDService struct {
+ clientset kubernetes.Interface
+ namespace string
+ settingsMgr *settings.SettingsManager
+ repoServerClient apiclient.RepoServerServiceClient
+ dispose func()
+}
+
+func (svc *argoCDService) GetCommitMetadata(ctx context.Context, repoURL string, commitSHA string) (*shared.CommitMetadata, error) {
+ argocdDB := db.NewDB(svc.namespace, svc.settingsMgr, svc.clientset)
+ repo, err := argocdDB.GetRepository(ctx, repoURL)
+ if err != nil {
+ return nil, err
+ }
+ metadata, err := svc.repoServerClient.GetRevisionMetadata(ctx, &apiclient.RepoServerRevisionMetadataRequest{
+ Repo: repo,
+ Revision: commitSHA,
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &shared.CommitMetadata{
+ Message: metadata.Message,
+ Author: metadata.Author,
+ Date: metadata.Date.Time,
+ Tags: metadata.Tags,
+ }, nil
+}
+
+func (svc *argoCDService) Close() {
+ svc.dispose()
+}
diff --git a/shared/settings/settings.go b/shared/settings/settings.go
index a9d4f8ea..2a96f745 100644
--- a/shared/settings/settings.go
+++ b/shared/settings/settings.go
@@ -4,6 +4,7 @@ import (
"encoding/json"
"github.com/argoproj-labs/argocd-notifications/notifiers"
+ "github.com/argoproj-labs/argocd-notifications/shared/argocd"
"github.com/argoproj-labs/argocd-notifications/triggers"
"github.com/ghodss/yaml"
@@ -133,7 +134,7 @@ func (cfg *Config) Merge(other *Config) (*Config, error) {
}
// ParseConfig parses notifications configuration from the provided config map and secret.
-func ParseConfig(configMap *v1.ConfigMap, secret *v1.Secret, defaultCfg Config) (map[string]triggers.Trigger, map[string]notifiers.Notifier, *Config, error) {
+func ParseConfig(configMap *v1.ConfigMap, secret *v1.Secret, defaultCfg Config, argocdService argocd.Service) (map[string]triggers.Trigger, map[string]notifiers.Notifier, *Config, error) {
cfg, err := ParseConfigMap(configMap)
if err != nil {
return nil, nil, nil, err
@@ -142,7 +143,7 @@ func ParseConfig(configMap *v1.ConfigMap, secret *v1.Secret, defaultCfg Config)
if err != nil {
return nil, nil, nil, err
}
- t, err := triggers.GetTriggers(cfg.Templates, cfg.Triggers)
+ t, err := triggers.GetTriggers(cfg.Templates, cfg.Triggers, argocdService)
if err != nil {
return nil, nil, nil, err
}
diff --git a/testing/testing.go b/testing/testing.go
index 58db4d6c..531569b0 100644
--- a/testing/testing.go
+++ b/testing/testing.go
@@ -84,6 +84,12 @@ func WithHealthStatus(status string) func(app *unstructured.Unstructured) {
}
}
+func WithRepoURL(repo string) func(app *unstructured.Unstructured) {
+ return func(app *unstructured.Unstructured) {
+ _ = unstructured.SetNestedField(app.Object, repo, "spec", "source", "repoURL")
+ }
+}
+
func NewApp(name string, modifiers ...func(app *unstructured.Unstructured)) *unstructured.Unstructured {
app := unstructured.Unstructured{}
app.SetGroupVersionKind(schema.GroupVersionKind{Group: "argoproj.io", Kind: "application", Version: "v1alpha1"})
diff --git a/triggers/expr/expr.go b/triggers/expr/expr.go
index 554a5af4..45e2ad85 100644
--- a/triggers/expr/expr.go
+++ b/triggers/expr/expr.go
@@ -1,8 +1,10 @@
package expr
import (
+ "github.com/argoproj-labs/argocd-notifications/shared/argocd"
"github.com/argoproj-labs/argocd-notifications/triggers/expr/repo"
"github.com/argoproj-labs/argocd-notifications/triggers/expr/time"
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
var helpers = map[string]interface{}{}
@@ -10,18 +12,18 @@ var helpers = map[string]interface{}{}
func init() {
helpers = make(map[string]interface{})
register("time", time.NewExprs())
- register("repo", repo.NewExprs())
}
func register(namespace string, entry map[string]interface{}) {
helpers[namespace] = entry
}
-func Spawn() map[string]interface{} {
+func Spawn(app *unstructured.Unstructured, argocdService argocd.Service) map[string]interface{} {
clone := make(map[string]interface{})
for namespace, helper := range helpers {
clone[namespace] = helper
}
+ clone["repo"] = repo.NewExprs(argocdService, app)
return clone
}
diff --git a/triggers/expr/expr_test.go b/triggers/expr/expr_test.go
index 30d2f272..196e5e97 100644
--- a/triggers/expr/expr_test.go
+++ b/triggers/expr/expr_test.go
@@ -13,7 +13,7 @@ func TestExpr(t *testing.T) {
}
for _, ns := range namespaces {
- helpers := Spawn()
+ helpers := Spawn(nil, nil)
_, hasNamespace := helpers[ns]
assert.True(t, hasNamespace)
}
diff --git a/triggers/expr/repo/repo.go b/triggers/expr/repo/repo.go
index f5cf05f9..7e10f89b 100644
--- a/triggers/expr/repo/repo.go
+++ b/triggers/expr/repo/repo.go
@@ -1,18 +1,38 @@
package repo
import (
+ "context"
+ "errors"
"regexp"
"strings"
- "github.com/argoproj-labs/argocd-notifications/shared/text"
-
giturls "github.com/whilp/git-urls"
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+
+ "github.com/argoproj-labs/argocd-notifications/shared/argocd"
+ "github.com/argoproj-labs/argocd-notifications/shared/text"
+ "github.com/argoproj-labs/argocd-notifications/triggers/expr/shared"
)
var (
gitSuffix = regexp.MustCompile(`\.git$`)
)
+func getCommitMetadata(commitSHA string, app *unstructured.Unstructured, argocdService argocd.Service) (*shared.CommitMetadata, error) {
+ repoURL, ok, err := unstructured.NestedString(app.Object, "spec", "source", "repoURL")
+ if err != nil {
+ return nil, err
+ }
+ if !ok {
+ panic(errors.New("failed to get application source repo URL"))
+ }
+ meta, err := argocdService.GetCommitMetadata(context.Background(), repoURL, commitSHA)
+ if err != nil {
+ return nil, err
+ }
+ return meta, nil
+}
+
func fullNameByRepoURL(rawURL string) string {
parsed, err := giturls.Parse(rawURL)
if err != nil {
@@ -37,9 +57,17 @@ func repoURLToHTTPS(rawURL string) string {
return parsed.String()
}
-func NewExprs() map[string]interface{} {
+func NewExprs(argocdService argocd.Service, app *unstructured.Unstructured) map[string]interface{} {
return map[string]interface{}{
"RepoURLToHTTPS": repoURLToHTTPS,
"FullNameByRepoURL": fullNameByRepoURL,
+ "GetCommitMetadata": func(commitSHA string) interface{} {
+ meta, err := getCommitMetadata(commitSHA, app, argocdService)
+ if err != nil {
+ panic(err)
+ }
+
+ return *meta
+ },
}
}
diff --git a/triggers/expr/repo/repo_test.go b/triggers/expr/repo/repo_test.go
index cb820f75..46570d8f 100644
--- a/triggers/expr/repo/repo_test.go
+++ b/triggers/expr/repo/repo_test.go
@@ -1,9 +1,15 @@
package repo
import (
+ "context"
"testing"
+ "github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
+
+ "github.com/argoproj-labs/argocd-notifications/shared/argocd/mocks"
+ . "github.com/argoproj-labs/argocd-notifications/testing"
+ "github.com/argoproj-labs/argocd-notifications/triggers/expr/shared"
)
func TestToHttps(t *testing.T) {
@@ -29,3 +35,19 @@ func TestParseFullName(t *testing.T) {
assert.Equal(t, actual, expected)
}
}
+
+func TestGetCommitMetadata(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
+ argocdService := mocks.NewMockService(ctrl)
+ expectedMeta := &shared.CommitMetadata{Message: "hello"}
+ argocdService.EXPECT().GetCommitMetadata(context.Background(), "http://myrepo-url.git", "abc").Return(expectedMeta, nil)
+ commitMeta, err := getCommitMetadata("abc", NewApp("guestbook", WithRepoURL("http://myrepo-url.git")), argocdService)
+
+ if !assert.NoError(t, err) {
+ return
+ }
+ assert.Equal(t, expectedMeta, commitMeta)
+
+}
diff --git a/triggers/expr/shared/commit.go b/triggers/expr/shared/commit.go
new file mode 100644
index 00000000..c58fa9a8
--- /dev/null
+++ b/triggers/expr/shared/commit.go
@@ -0,0 +1,16 @@
+package shared
+
+import (
+ "time"
+)
+
+type CommitMetadata struct {
+ // Commit message
+ Message string
+ // Commit author
+ Author string
+ // Commit creation date
+ Date time.Time
+ // Associated tags
+ Tags []string
+}
diff --git a/triggers/triggers.go b/triggers/triggers.go
index 055051c1..b747d6f5 100644
--- a/triggers/triggers.go
+++ b/triggers/triggers.go
@@ -7,12 +7,13 @@ import (
"fmt"
texttemplate "text/template"
+ "github.com/Masterminds/sprig"
"github.com/antonmedv/expr"
"github.com/antonmedv/expr/vm"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
- "github.com/Masterminds/sprig"
"github.com/argoproj-labs/argocd-notifications/notifiers"
+ "github.com/argoproj-labs/argocd-notifications/shared/argocd"
exprHelpers "github.com/argoproj-labs/argocd-notifications/triggers/expr"
)
@@ -50,12 +51,12 @@ type template struct {
webhooks map[string]webhookTemplate
}
-func (tmpl template) formatNotification(app *unstructured.Unstructured, context map[string]string) (*notifiers.Notification, error) {
+func (tmpl template) formatNotification(app *unstructured.Unstructured, context map[string]string, argocdService argocd.Service) (*notifiers.Notification, error) {
vars := map[string]interface{}{
"app": app.Object,
"context": context,
}
- for k, v := range exprHelpers.Spawn() {
+ for k, v := range exprHelpers.Spawn(app, argocdService) {
vars[k] = v
}
var title bytes.Buffer
@@ -111,20 +112,21 @@ func (tmpl template) formatNotification(app *unstructured.Unstructured, context
}
type trigger struct {
- condition *vm.Program
- template template
+ condition *vm.Program
+ template template
+ argocdService argocd.Service
}
-func GetTriggers(templatesCfg []NotificationTemplate, triggersCfg []NotificationTrigger) (map[string]Trigger, error) {
+func GetTriggers(templatesCfg []NotificationTemplate, triggersCfg []NotificationTrigger, argocdService argocd.Service) (map[string]Trigger, error) {
templates, err := parseTemplates(templatesCfg)
if err != nil {
return nil, err
}
- return parseTriggers(triggersCfg, templates)
+ return parseTriggers(triggersCfg, templates, argocdService)
}
-func spawnExprEnvs(opts map[string]interface{}) interface{} {
- envs := exprHelpers.Spawn()
+func spawnExprEnvs(app *unstructured.Unstructured, opts map[string]interface{}, argocdService argocd.Service) interface{} {
+ envs := exprHelpers.Spawn(app, argocdService)
for name, env := range opts {
envs[name] = env
}
@@ -134,7 +136,7 @@ func spawnExprEnvs(opts map[string]interface{}) interface{} {
func (t *trigger) Triggered(app *unstructured.Unstructured) (bool, error) {
envs := map[string]interface{}{"app": app.Object}
- if res, err := expr.Run(t.condition, spawnExprEnvs(envs)); err != nil {
+ if res, err := expr.Run(t.condition, spawnExprEnvs(app, envs, t.argocdService)); err != nil {
return false, err
} else if boolRes, ok := res.(bool); ok {
return boolRes, nil
@@ -147,7 +149,7 @@ func (t *trigger) GetTemplateName() string {
}
func (t *trigger) FormatNotification(app *unstructured.Unstructured, context map[string]string) (*notifiers.Notification, error) {
- return t.template.formatNotification(app, context)
+ return t.template.formatNotification(app, context, t.argocdService)
}
func parseTemplates(templates []NotificationTemplate) (map[string]template, error) {
@@ -205,7 +207,7 @@ func parseTemplate(nt NotificationTemplate, f texttemplate.FuncMap) (*template,
return &t, nil
}
-func parseTriggers(triggers []NotificationTrigger, templates map[string]template) (map[string]Trigger, error) {
+func parseTriggers(triggers []NotificationTrigger, templates map[string]template, argocdService argocd.Service) (map[string]Trigger, error) {
res := make(map[string]Trigger)
for _, t := range triggers {
if t.Enabled != nil && !*t.Enabled {
@@ -222,7 +224,7 @@ func parseTriggers(triggers []NotificationTrigger, templates map[string]template
if !ok {
return nil, fmt.Errorf("trigger %s references unknown template %s", t.Name, t.Template)
}
- res[t.Name] = &trigger{condition: condition, template: template}
+ res[t.Name] = &trigger{condition: condition, template: template, argocdService: argocdService}
}
return res, nil
}
diff --git a/triggers/triggers_test.go b/triggers/triggers_test.go
index b42a43bc..23683170 100644
--- a/triggers/triggers_test.go
+++ b/triggers/triggers_test.go
@@ -16,7 +16,7 @@ func TestGetTriggers_FailsIfReferencesNonExistingTemplate(t *testing.T) {
Name: "test",
Template: "bad",
Condition: "true",
- }})
+ }}, nil)
assert.EqualError(t, err, "trigger test references unknown template bad")
}
@@ -31,7 +31,7 @@ func TestGetTriggers(t *testing.T) {
Name: "trigger",
Template: "template",
Condition: "app.metadata.name == 'foo'",
- }})
+ }}, nil)
assert.NoError(t, err)
trigger, ok := triggers["trigger"]
@@ -62,7 +62,7 @@ func TestGetTriggers_UsingContext(t *testing.T) {
Name: "trigger",
Template: "template",
Condition: "app.metadata.name == 'foo'",
- }})
+ }}, nil)
assert.NoError(t, err)
trigger, ok := triggers["trigger"]
@@ -97,7 +97,7 @@ func TestGetTriggers_UsingSlack(t *testing.T) {
Name: "trigger",
Template: "template",
Condition: "app.metadata.name == 'foo'",
- }})
+ }}, nil)
assert.NoError(t, err)
trigger, ok := triggers["trigger"]
@@ -121,7 +121,7 @@ func TestGetTriggers_UsingSlack(t *testing.T) {
func TestSpawnExprEnvs(t *testing.T) {
opts := map[string]interface{}{"app": "dummy"}
- envs, ok := spawnExprEnvs(opts).(map[string]interface{})
+ envs, ok := spawnExprEnvs(testingutil.NewApp("test"), opts, nil).(map[string]interface{})
assert.True(t, ok)
_, hasApp := envs["app"]
@@ -139,7 +139,7 @@ func TestGetTriggers_UsingExprVm(t *testing.T) {
Name: "trigger",
Template: "template",
Condition: "app.metadata.name == 'foo' && app.status.operationState.phase in ['Running'] && time.Now().Sub(time.Parse(app.status.operationState.startedAt)).Minutes() >= 5",
- }})
+ }}, nil)
assert.NoError(t, err)
trigger, ok := triggers["trigger"]
@@ -179,7 +179,7 @@ func TestTrigger_FormatWebhookNotification(t *testing.T) {
return
}
- nt, err := testTemplate.formatNotification(testingutil.NewApp("world"), map[string]string{})
+ nt, err := testTemplate.formatNotification(testingutil.NewApp("world"), map[string]string{}, nil)
if !assert.NoError(t, err) {
return
}