Skip to content

Commit

Permalink
daemon(deployment): integrate slack config (#661)
Browse files Browse the repository at this point in the history
* chore: fix counterfeiter runner
* daemon(notify): add equality checker
  • Loading branch information
bobheadxi committed Mar 22, 2020
1 parent 76f3cee commit f386362
Show file tree
Hide file tree
Showing 12 changed files with 199 additions and 26 deletions.
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -207,13 +207,13 @@ docker-deps:
## mocks: generate Go mocks
.PHONY: mocks
mocks:
counterfeiter -o ./client/runner/mocks/session.go \
go run github.com/maxbrunsfeld/counterfeiter/v6 -o ./client/runner/mocks/session.go \
./client/runner/ssh.go SSHSession
counterfeiter -o ./daemon/inertiad/project/mocks/deployer.go \
go run github.com/maxbrunsfeld/counterfeiter/v6 -o ./daemon/inertiad/project/mocks/deployer.go \
./daemon/inertiad/project/deployment.go Deployer
counterfeiter -o ./daemon/inertiad/build/mocks/builder.go \
go run github.com/maxbrunsfeld/counterfeiter/v6 -o ./daemon/inertiad/build/mocks/builder.go \
./daemon/inertiad/build/builder.go ContainerBuilder
counterfeiter -o ./daemon/inertiad/notify/mocks/notify.go \
go run github.com/maxbrunsfeld/counterfeiter/v6 -o ./daemon/inertiad/notify/mocks/notify.go \
./daemon/inertiad/notify/notifier.go Notifier

## scripts: recompile script assets
Expand Down
1 change: 1 addition & 0 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type UpRequest struct {
GitOptions GitOptions `json:"git_options"`
WebHookSecret string `json:"webhook_secret"`
IntermediaryContainers []string `json:"intermediary_containers"`
SlackNotificationURL string `json:"slack_notification_url"`
}

// GitOptions represents GitHub-related deployment options
Expand Down
12 changes: 9 additions & 3 deletions cfg/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ type Project struct {

// Profile denotes a deployment configuration
type Profile struct {
Name string `toml:"name"`
Branch string `toml:"branch"`
Build *Build `toml:"build"`
Name string `toml:"name"`
Branch string `toml:"branch"`
Build *Build `toml:"build"`
Notifiers *Notifiers `toml:"notifiers"`
}

// Identifier implements identity.Identifier
Expand Down Expand Up @@ -104,3 +105,8 @@ func (p *Project) RemoveProfile(name string) bool {
p.Profiles = asProfiles(ids)
return ok
}

// Notifiers defines options for notifications on a profile
type Notifiers struct {
SlackNotificationURL string `toml:"slack_notification_url"`
}
6 changes: 6 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ type UpRequest struct {
// Up brings the project up on the remote VPS instance specified
// in the deployment object.
func (c *Client) Up(ctx context.Context, req UpRequest) error {
notif := req.Profile.Notifiers
if notif == nil {
notif = &cfg.Notifiers{}
}

resp, err := c.post(ctx, "/up", &api.UpRequest{
Stream: false,
Project: req.Project,
Expand All @@ -103,6 +108,7 @@ func (c *Client) Up(ctx context.Context, req UpRequest) error {
Branch: req.Profile.Branch,
},
IntermediaryContainers: req.Profile.Build.IntermediaryContainers,
SlackNotificationURL: notif.SlackNotificationURL,
})
if err != nil {
return fmt.Errorf("failed to make request: %s", err.Error())
Expand Down
19 changes: 6 additions & 13 deletions daemon/inertiad/daemon/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,17 @@ func (s *Server) upHandler(w http.ResponseWriter, r *http.Request) {
if upReq.WebHookSecret != "" {
s.state.WebhookSecret = upReq.WebHookSecret
}
s.deployment.SetConfig(project.DeploymentConfig{
conf := project.DeploymentConfig{
ProjectName: upReq.Project,
BuildType: upReq.BuildType,
BuildFilePath: upReq.BuildFilePath,
RemoteURL: gitOpts.RemoteURL,
Branch: gitOpts.Branch,
PemFilePath: crypto.DaemonGithubKeyLocation,
IntermediaryContainers: upReq.IntermediaryContainers,
})
SlackNotificationURL: upReq.SlackNotificationURL,
}
s.deployment.SetConfig(conf)

// Configure streamer
var stream = log.NewStreamer(log.StreamerOptions{
Expand All @@ -55,17 +58,7 @@ func (s *Server) upHandler(w http.ResponseWriter, r *http.Request) {
var skipUpdate = false
if status, _ := s.deployment.GetStatus(s.docker); status.CommitHash == "" {
stream.Println("No deployment detected")
if err = s.deployment.Initialize(
project.DeploymentConfig{
ProjectName: upReq.Project,
BuildType: upReq.BuildType,
BuildFilePath: upReq.BuildFilePath,
RemoteURL: gitOpts.RemoteURL,
Branch: gitOpts.Branch,
PemFilePath: crypto.DaemonGithubKeyLocation,
},
stream,
); err != nil {
if err = s.deployment.Initialize(conf, stream); err != nil {
stream.Error(res.Err(err.Error(), http.StatusPreconditionFailed))
return
}
Expand Down
73 changes: 73 additions & 0 deletions daemon/inertiad/notify/mocks/notify.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions daemon/inertiad/notify/notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,20 @@ func (n Notifiers) Notify(msg string, opts Options) error {
return errs
}

// Exists checks if the given notifier is already configured
func (n Notifiers) Exists(nt Notifier) bool {
for _, notif := range n {
if notif.IsEqual(nt) {
return true
}
}
return false
}

// Notifier manages notifications
type Notifier interface {
Notify(string, Options) error
IsEqual(Notifier) bool
}

// Options is used to configure formatting of notifications
Expand Down
26 changes: 26 additions & 0 deletions daemon/inertiad/notify/notifier_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package notify

import "testing"

func TestNotifiers_Exists(t *testing.T) {
type args struct {
nt Notifier
}
tests := []struct {
name string
n Notifiers
args args
want bool
}{
{"ok: exists", Notifiers{&SlackNotifier{"abcde"}}, args{&SlackNotifier{"abcde"}}, true},
{"not ok: no notifiers", Notifiers{}, args{&SlackNotifier{"abcde"}}, false},
{"not ok: doesnt exist", Notifiers{&SlackNotifier{"robert"}}, args{&SlackNotifier{"abcde"}}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.n.Exists(tt.args.nt); got != tt.want {
t.Errorf("Notifiers.Exists() = %v, want %v", got, tt.want)
}
})
}
}
11 changes: 11 additions & 0 deletions daemon/inertiad/notify/slack.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ func (n *SlackNotifier) Notify(text string, options Options) error {
return nil
}

// IsEqual implements Notifier by checking the provided notifier is a slack notifier
// and if it has the same hook URL
func (n *SlackNotifier) IsEqual(nt Notifier) bool {
switch v := nt.(type) {
case *SlackNotifier:
return n.hookURL == v.hookURL
default:
return false
}
}

func colorToString(color Color) string {
return string(color)
}
32 changes: 32 additions & 0 deletions daemon/inertiad/notify/slack_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package notify

import "testing"

func TestSlackNotifier_IsEqual(t *testing.T) {
type fields struct {
hookURL string
}
type args struct {
nt Notifier
}
tests := []struct {
name string
fields fields
args args
want bool
}{
{"ok: same hook url", fields{"abcde"}, args{&SlackNotifier{"abcde"}}, true},
{"not ok: diff hook url", fields{"robert"}, args{&SlackNotifier{"abcde"}}, false},
{"not ok: not slack notifier", fields{"robert"}, args{nil}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
n := &SlackNotifier{
hookURL: tt.fields.hookURL,
}
if got := n.IsEqual(tt.args.nt); got != tt.want {
t.Errorf("SlackNotifier.IsEqual() = %v, want %v", got, tt.want)
}
})
}
}
16 changes: 14 additions & 2 deletions daemon/inertiad/project/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ type DeploymentConfig struct {
Branch string
PemFilePath string
IntermediaryContainers []string

// TODO: maybe improve format for generic notifiers
SlackNotificationURL string
}

// DeploymentMetadata is used to store metadata relevant
Expand Down Expand Up @@ -166,7 +169,16 @@ func (d *Deployment) SetConfig(cfg DeploymentConfig) {
}
d.intermediaryContainers = cfg.IntermediaryContainers

// TODO: register notifiers
// register notifiers
if len(d.notifiers) == 0 {
d.notifiers = notify.Notifiers{}
}
if cfg.SlackNotificationURL != "" {
nt := notify.NewSlackNotifier(cfg.SlackNotificationURL)
if !d.notifiers.Exists(nt) {
d.notifiers = append(d.notifiers, nt)
}
}
}

// DeployOptions is used to configure how the deployment handles the deploy
Expand Down Expand Up @@ -215,7 +227,7 @@ func (d *Deployment) Deploy(
// Build project
deploy, err := d.builder.Build(strings.ToLower(d.buildType), *conf, cli, out)
if err != nil {
if notifyErr := d.notifiers.Notify("Build error", notify.Options{
if notifyErr := d.notifiers.Notify(fmt.Sprintf("Build error: %s", err), notify.Options{
Color: notify.Red,
}); notifyErr != nil {
fmt.Fprintln(out, notifyErr.Error())
Expand Down
10 changes: 6 additions & 4 deletions daemon/inertiad/project/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,18 @@ func newDefaultFakeBuilder(builder func() error, stopper func() error) *mocks.Fa
func TestSetConfig(t *testing.T) {
deployment := &Deployment{}
deployment.SetConfig(DeploymentConfig{
ProjectName: "wow",
Branch: "amazing",
BuildType: "best",
BuildFilePath: "/robertcompose.yml",
ProjectName: "wow",
Branch: "amazing",
BuildType: "best",
BuildFilePath: "/robertcompose.yml",
SlackNotificationURL: "https://my.slack.url",
})

assert.Equal(t, "wow", deployment.project)
assert.Equal(t, "amazing", deployment.branch)
assert.Equal(t, "best", deployment.buildType)
assert.Equal(t, "/robertcompose.yml", deployment.buildFilePath)
assert.Len(t, deployment.notifiers, 1)
}

func TestDeployMock(t *testing.T) {
Expand Down

0 comments on commit f386362

Please sign in to comment.