open-nomad/vendor/github.com/linode/linodego/account_events.go
Seth Hoenig 435c0d9fc8 deps: Switch to Go modules for dependency management
This PR switches the Nomad repository from using govendor to Go modules
for managing dependencies. Aspects of the Nomad workflow remain pretty
much the same. The usual Makefile targets should continue to work as
they always did. The API submodule simply defers to the parent Nomad
version on the repository, keeping the semantics of API versioning that
currently exists.
2020-06-02 14:30:36 -05:00

278 lines
9.5 KiB
Go

package linodego
import (
"context"
"encoding/json"
"fmt"
"log"
"strconv"
"strings"
"time"
)
// Event represents an action taken on the Account.
type Event struct {
CreatedStr string `json:"created"`
// The unique ID of this Event.
ID int `json:"id"`
// Current status of the Event, Enum: "failed" "finished" "notification" "scheduled" "started"
Status EventStatus `json:"status"`
// The action that caused this Event. New actions may be added in the future.
Action EventAction `json:"action"`
// A percentage estimating the amount of time remaining for an Event. Returns null for notification events.
PercentComplete int `json:"percent_complete"`
// The rate of completion of the Event. Only some Events will return rate; for example, migration and resize Events.
Rate *string `json:"rate"`
// If this Event has been read.
Read bool `json:"read"`
// If this Event has been seen.
Seen bool `json:"seen"`
// The estimated time remaining until the completion of this Event. This value is only returned for in-progress events.
TimeRemainingMsg json.RawMessage `json:"time_remaining"`
TimeRemaining *int `json:"-"`
// The username of the User who caused the Event.
Username string `json:"username"`
// Detailed information about the Event's entity, including ID, type, label, and URL used to access it.
Entity *EventEntity `json:"entity"`
// When this Event was created.
Created *time.Time `json:"-"`
}
// EventAction constants start with Action and include all known Linode API Event Actions.
type EventAction string
// EventAction constants represent the actions that cause an Event. New actions may be added in the future.
const (
ActionBackupsEnable EventAction = "backups_enable"
ActionBackupsCancel EventAction = "backups_cancel"
ActionBackupsRestore EventAction = "backups_restore"
ActionCommunityQuestionReply EventAction = "community_question_reply"
ActionCreateCardUpdated EventAction = "credit_card_updated"
ActionDiskCreate EventAction = "disk_create"
ActionDiskDelete EventAction = "disk_delete"
ActionDiskDuplicate EventAction = "disk_duplicate"
ActionDiskImagize EventAction = "disk_imagize"
ActionDiskResize EventAction = "disk_resize"
ActionDNSRecordCreate EventAction = "dns_record_create"
ActionDNSRecordDelete EventAction = "dns_record_delete"
ActionDNSZoneCreate EventAction = "dns_zone_create"
ActionDNSZoneDelete EventAction = "dns_zone_delete"
ActionImageDelete EventAction = "image_delete"
ActionLinodeAddIP EventAction = "linode_addip"
ActionLinodeBoot EventAction = "linode_boot"
ActionLinodeClone EventAction = "linode_clone"
ActionLinodeCreate EventAction = "linode_create"
ActionLinodeDelete EventAction = "linode_delete"
ActionLinodeDeleteIP EventAction = "linode_deleteip"
ActionLinodeMigrate EventAction = "linode_migrate"
ActionLinodeMutate EventAction = "linode_mutate"
ActionLinodeReboot EventAction = "linode_reboot"
ActionLinodeRebuild EventAction = "linode_rebuild"
ActionLinodeResize EventAction = "linode_resize"
ActionLinodeShutdown EventAction = "linode_shutdown"
ActionLinodeSnapshot EventAction = "linode_snapshot"
ActionLongviewClientCreate EventAction = "longviewclient_create"
ActionLongviewClientDelete EventAction = "longviewclient_delete"
ActionManagedDisabled EventAction = "managed_disabled"
ActionManagedEnabled EventAction = "managed_enabled"
ActionManagedServiceCreate EventAction = "managed_service_create"
ActionManagedServiceDelete EventAction = "managed_service_delete"
ActionNodebalancerCreate EventAction = "nodebalancer_create"
ActionNodebalancerDelete EventAction = "nodebalancer_delete"
ActionNodebalancerConfigCreate EventAction = "nodebalancer_config_create"
ActionNodebalancerConfigDelete EventAction = "nodebalancer_config_delete"
ActionPasswordReset EventAction = "password_reset"
ActionPaymentSubmitted EventAction = "payment_submitted"
ActionStackScriptCreate EventAction = "stackscript_create"
ActionStackScriptDelete EventAction = "stackscript_delete"
ActionStackScriptPublicize EventAction = "stackscript_publicize"
ActionStackScriptRevise EventAction = "stackscript_revise"
ActionTFADisabled EventAction = "tfa_disabled"
ActionTFAEnabled EventAction = "tfa_enabled"
ActionTicketAttachmentUpload EventAction = "ticket_attachment_upload"
ActionTicketCreate EventAction = "ticket_create"
ActionTicketReply EventAction = "ticket_reply"
ActionVolumeAttach EventAction = "volume_attach"
ActionVolumeClone EventAction = "volume_clone"
ActionVolumeCreate EventAction = "volume_create"
ActionVolumeDelte EventAction = "volume_delete"
ActionVolumeDetach EventAction = "volume_detach"
ActionVolumeResize EventAction = "volume_resize"
)
// EntityType constants start with Entity and include Linode API Event Entity Types
type EntityType string
// EntityType contants are the entities an Event can be related to
const (
EntityLinode EntityType = "linode"
EntityDisk EntityType = "disk"
)
// EventStatus constants start with Event and include Linode API Event Status values
type EventStatus string
// EventStatus constants reflect the current status of an Event
const (
EventFailed EventStatus = "failed"
EventFinished EventStatus = "finished"
EventNotification EventStatus = "notification"
EventScheduled EventStatus = "scheduled"
EventStarted EventStatus = "started"
)
// EventEntity provides detailed information about the Event's
// associated entity, including ID, Type, Label, and a URL that
// can be used to access it.
type EventEntity struct {
// ID may be a string or int, it depends on the EntityType
ID interface{} `json:"id"`
Label string `json:"label"`
Type EntityType `json:"type"`
URL string `json:"url"`
}
// EventsPagedResponse represents a paginated Events API response
type EventsPagedResponse struct {
*PageOptions
Data []Event `json:"data"`
}
// endpoint gets the endpoint URL for Event
func (EventsPagedResponse) endpoint(c *Client) string {
endpoint, err := c.Events.Endpoint()
if err != nil {
panic(err)
}
return endpoint
}
// endpointWithID gets the endpoint URL for a specific Event
func (e Event) endpointWithID(c *Client) string {
endpoint, err := c.Events.Endpoint()
if err != nil {
panic(err)
}
endpoint = fmt.Sprintf("%s/%d", endpoint, e.ID)
return endpoint
}
// appendData appends Events when processing paginated Event responses
func (resp *EventsPagedResponse) appendData(r *EventsPagedResponse) {
resp.Data = append(resp.Data, r.Data...)
}
// ListEvents gets a collection of Event objects representing actions taken
// on the Account. The Events returned depend on the token grants and the grants
// of the associated user.
func (c *Client) ListEvents(ctx context.Context, opts *ListOptions) ([]Event, error) {
response := EventsPagedResponse{}
err := c.listHelper(ctx, &response, opts)
for i := range response.Data {
response.Data[i].fixDates()
}
if err != nil {
return nil, err
}
return response.Data, nil
}
// GetEvent gets the Event with the Event ID
func (c *Client) GetEvent(ctx context.Context, id int) (*Event, error) {
e, err := c.Events.Endpoint()
if err != nil {
return nil, err
}
e = fmt.Sprintf("%s/%d", e, id)
r, err := c.R(ctx).SetResult(&Event{}).Get(e)
if err != nil {
return nil, err
}
return r.Result().(*Event).fixDates(), nil
}
// fixDates converts JSON timestamps to Go time.Time values
func (e *Event) fixDates() *Event {
e.Created, _ = parseDates(e.CreatedStr)
e.TimeRemaining = unmarshalTimeRemaining(e.TimeRemainingMsg)
return e
}
// MarkEventRead marks a single Event as read.
func (c *Client) MarkEventRead(ctx context.Context, event *Event) error {
e := event.endpointWithID(c)
e = fmt.Sprintf("%s/read", e)
_, err := coupleAPIErrors(c.R(ctx).Post(e))
return err
}
// MarkEventsSeen marks all Events up to and including this Event by ID as seen.
func (c *Client) MarkEventsSeen(ctx context.Context, event *Event) error {
e := event.endpointWithID(c)
e = fmt.Sprintf("%s/seen", e)
_, err := coupleAPIErrors(c.R(ctx).Post(e))
return err
}
func unmarshalTimeRemaining(m json.RawMessage) *int {
jsonBytes, err := m.MarshalJSON()
if err != nil {
panic(jsonBytes)
}
if len(jsonBytes) == 4 && string(jsonBytes) == "null" {
return nil
}
var timeStr string
if err := json.Unmarshal(jsonBytes, &timeStr); err == nil && len(timeStr) > 0 {
if dur, err := durationToSeconds(timeStr); err != nil {
panic(err)
} else {
return &dur
}
} else {
var intPtr int
if err := json.Unmarshal(jsonBytes, &intPtr); err == nil {
return &intPtr
}
}
log.Println("[WARN] Unexpected unmarshalTimeRemaining value: ", jsonBytes)
return nil
}
// durationToSeconds takes a hh:mm:ss string and returns the number of seconds
func durationToSeconds(s string) (int, error) {
multipliers := [3]int{60 * 60, 60, 1}
segs := strings.Split(s, ":")
if len(segs) > len(multipliers) {
return 0, fmt.Errorf("too many ':' separators in time duration: %s", s)
}
var d int
l := len(segs)
for i := 0; i < l; i++ {
m, err := strconv.Atoi(segs[i])
if err != nil {
return 0, err
}
d += m * multipliers[i+len(multipliers)-l]
}
return d, nil
}