Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added alert contacts data to getMonitor and getAllMonitors methods. #26

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ uptimerobot*
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
.vscode/spellright.dict
.idea/
44 changes: 44 additions & 0 deletions pkg/alert_contact.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package uptimerobot

import "fmt"

// AlertContact represents an alert contact.
type AlertContact struct {
ID string `json:"id"`
Expand All @@ -19,3 +21,45 @@ Value: {{ .Value }}`
func (a AlertContact) String() string {
return render(alertContactTemplate, a)
}

// FriendlyType returns a human-readable name for the alert contact type
func (a AlertContact) FriendlyType() string {
switch a.Type {
case AlertContactTypePrimaryEmail:
return "PrimaryEmail"
case AlertContactTypeEmail:
return "Email"
case AlertContactTypeSms:
return "Sms"
case AlertContactTypeVoiceCall:
return "Voice"
case AlertContactTypeWebHook:
return "Webhook"
case AlertContactTypeEmailToSms:
return "EmailToSms"
case AlertContactTypeTwitter:
return "Twitter"
case AlertContactTypeTelegram:
return "Telegram"
case AlertContactTypeSlack:
return "Slack"
case AlertContactTypeTeams:
return "Teams"
case AlertContactTypeGoogleChat:
return "GoogleChat"
case AlertContactTypeHipChat:
return "HipChat"
case AlertContactTypePagerDuty:
return "Pagerduty"
case AlertContactTypePushbullet:
return "Pushbullet"
case AlertContactTypePushover:
return "Pushover"
case AlertContactTypeVictorOps:
return "VictorOps"
case AlertContactTypeZaiper:
return "Zaiper"
default:
return fmt.Sprintf("%d", a.Type)
}
}
4 changes: 2 additions & 2 deletions pkg/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (c *Client) GetAccountDetails() (Account, error) {
// and returns the corresponding Monitor, or an error if the operation failed.
func (c *Client) GetMonitor(ID int64) (Monitor, error) {
r := Response{}
data := []byte(fmt.Sprintf("{\"monitors\": \"%d\"}", ID))
data := []byte(fmt.Sprintf("{\"monitors\": \"%d\", \"alert_contacts\": \"1\"}", ID))
if err := c.MakeAPICall("getMonitors", &r, data); err != nil {
return Monitor{}, err
}
Expand All @@ -105,7 +105,7 @@ func (c *Client) AllMonitors() ([]Monitor, error) {
offset := 0
r := Response{}
for offset <= r.Pagination.Total {
data := []byte(fmt.Sprintf("{\"offset\": \"%d\", \"limit\": \"%d\"}", offset, maxRecordsPerRequest))
data := []byte(fmt.Sprintf("{\"offset\": \"%d\", \"limit\": \"%d\", \"alert_contacts\": \"1\"}", offset, maxRecordsPerRequest))
if err := c.MakeAPICall("getMonitors", &r, data); err != nil {
return nil, err
}
Expand Down
21 changes: 21 additions & 0 deletions pkg/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,24 @@ const StatusMaybeDown = 8

// StatusDown is the status value indicating that the monitor is currently down.
const StatusDown = 9

// AlertContactType is a predefined values from uptimerobot. Need for using AlertContact friendly type.
const (
AlertContactTypePrimaryEmail = 0
AlertContactTypeEmailToSms = 1
AlertContactTypeEmail = 2
This conversation was marked as resolved.
Show resolved Hide resolved
AlertContactTypeTwitter = 3
AlertContactTypeWebHook = 5
AlertContactTypePushbullet = 6
AlertContactTypeZaiper = 7
AlertContactTypeSms = 8
AlertContactTypePushover = 9
AlertContactTypeHipChat = 10
AlertContactTypeSlack = 11
AlertContactTypeVoiceCall = 14
AlertContactTypeVictorOps = 15
AlertContactTypePagerDuty = 16
AlertContactTypeTelegram = 18
AlertContactTypeTeams = 20
AlertContactTypeGoogleChat = 21
)
14 changes: 14 additions & 0 deletions pkg/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
)

// Monitor represents an Uptime Robot monitor.
// AlertContacts in Monitor struct is not equal AlertContact type. Here we just have array of AlertContact IDs in a string representation
type Monitor struct {
ID int64 `json:"id,omitempty"`
FriendlyName string `json:"friendly_name"`
Expand Down Expand Up @@ -169,6 +170,19 @@ func (m *Monitor) UnmarshalJSON(data []byte) error {
raw[f] = v
}
}
// We don't need full AlertContact structure, we need only its ID
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, if we're going to do this, we might as well define the proper struct!

Copy link
Author

@ghost ghost Dec 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proper struct defined for the Monitor (pkg/monitor.go). This was not changed. There we have

type Monitor struct {
        ...
	AlertContacts []string `json:"alert_contacts,omitempty"`
        ...
}

And in the pkg/alert_contact.go we have

type AlertContact struct {
	ID           string `json:"id"`
        ...
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I misunderstood your comment, then. I thought you were saying you weren't going to unmarshal the complete struct. Are you?

Copy link
Author

@ghost ghost Dec 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. We have a structure for AlertContact, and we have field AlertContacts (type []string) in Monitor structure. We don't need complete AlertContact struct in Monotor, that's why I used only AlertContact.Id.

May be I misunderstood your first question. What did you mean by

Well, if we're going to do this, we might as well define the proper struct!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bitfield Are you still remember about this?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't forgotten about this, but it needs a non-trivial amount of time to get my head back into this project and review your code properly. I'll try to get to it as soon as I can!

for key, _ := range raw {
if key == "alert_contacts" {
var alertContactsId []string
alertContacts := raw[key].([]interface{})
for _, ac := range alertContacts {
alertContact := ac.(map[string]interface{})
alertContactsId = append(alertContactsId, alertContact["id"].(string))
}
raw[key] = alertContactsId
}
}

// Marshal the cleaned-up data back to JSON
data, err = json.Marshal(raw)
if err != nil {
Expand Down
12 changes: 12 additions & 0 deletions pkg/uptimerobot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -590,3 +590,15 @@ func cannedResponseServer(t *testing.T, path string) *httptest.Server {
io.Copy(w, data)
}))
}

func TestAlertContactFriendlyType(t *testing.T) {
t.Parallel()
a := AlertContact{
Type: AlertContactTypeSlack,
}
want := "Slack"
got := a.FriendlyType()
if !cmp.Equal(want, got) {
t.Error(cmp.Diff(want, got))
}
}