166 lines
3.7 KiB
Go
166 lines
3.7 KiB
Go
package types
|
|
|
|
import (
|
|
"database/sql/driver"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
type GetApprovalQuery struct {
|
|
ID string
|
|
Identifier string
|
|
// Rejected bool
|
|
Archived bool
|
|
}
|
|
|
|
// Approval used to store and track updates
|
|
type Approval struct {
|
|
ID string `json:"id" gorm:"primary_key;type:varchar(36)"`
|
|
|
|
// Archived is set to true once approval is finally approved/rejected
|
|
Archived bool `json:"archived"`
|
|
|
|
// Provider name - Kubernetes/Helm
|
|
Provider ProviderType `json:"provider"`
|
|
|
|
// Identifier is used to inform user about specific
|
|
// Helm release or k8s deployment
|
|
// ie: k8s <namespace>/<deployment name>
|
|
// helm: <namespace>/<release name>
|
|
Identifier string `json:"identifier"`
|
|
|
|
// Event that triggered evaluation
|
|
Event *Event `json:"event" gorm:"type:json"`
|
|
|
|
Message string `json:"message"`
|
|
|
|
CurrentVersion string `json:"currentVersion"`
|
|
NewVersion string `json:"newVersion"`
|
|
|
|
// Digest is used to verify that images are the ones that got the approvals.
|
|
// If digest doesn't match for the image, votes are reset.
|
|
Digest string `json:"digest"`
|
|
|
|
// Requirements for the update such as number of votes
|
|
// and deadline
|
|
VotesRequired int `json:"votesRequired"`
|
|
VotesReceived int `json:"votesReceived"`
|
|
|
|
// Voters is a list of voter
|
|
// IDs for audit
|
|
Voters JSONB `json:"voters" gorm:"type:json"`
|
|
|
|
// Explicitly rejected approval
|
|
// can be set directly by user
|
|
// so even if deadline is not reached approval
|
|
// could be turned down
|
|
Rejected bool `json:"rejected"`
|
|
|
|
// Deadline for this request
|
|
Deadline time.Time `json:"deadline"`
|
|
|
|
// When this approval was created
|
|
CreatedAt time.Time `json:"createdAt"`
|
|
// WHen this approval was updated
|
|
UpdatedAt time.Time `json:"updatedAt"`
|
|
}
|
|
|
|
func (a *Approval) GetVoters() []string {
|
|
// meta := make(map[string]string)
|
|
var voters []string
|
|
for key := range a.Voters {
|
|
voters = append(voters, key)
|
|
|
|
}
|
|
return voters
|
|
}
|
|
|
|
func (a *Approval) AddVoter(voter string) {
|
|
if a.Voters == nil {
|
|
a.Voters = make(map[string]interface{})
|
|
}
|
|
a.Voters[voter] = time.Now()
|
|
}
|
|
|
|
// ApprovalStatus - approval status type used in approvals
|
|
// to determine whether it was rejected/approved or still pending
|
|
type ApprovalStatus int
|
|
|
|
// Available approval status types
|
|
const (
|
|
ApprovalStatusUnknown ApprovalStatus = iota
|
|
ApprovalStatusPending
|
|
ApprovalStatusApproved
|
|
ApprovalStatusRejected
|
|
)
|
|
|
|
func (s ApprovalStatus) String() string {
|
|
switch s {
|
|
case ApprovalStatusPending:
|
|
return "pending"
|
|
case ApprovalStatusApproved:
|
|
return "approved"
|
|
case ApprovalStatusRejected:
|
|
return "rejected"
|
|
default:
|
|
return "unknown"
|
|
}
|
|
}
|
|
|
|
// Status - returns current approval status
|
|
func (a *Approval) Status() ApprovalStatus {
|
|
if a.Rejected {
|
|
return ApprovalStatusRejected
|
|
}
|
|
|
|
if a.VotesReceived >= a.VotesRequired {
|
|
return ApprovalStatusApproved
|
|
}
|
|
|
|
return ApprovalStatusPending
|
|
}
|
|
|
|
// Expired - checks if approval is already expired
|
|
func (a *Approval) Expired() bool {
|
|
return a.Deadline.Before(time.Now())
|
|
}
|
|
|
|
// Delta of what's changed
|
|
// ie: webhookrelay/webhook-demo:0.15.0 -> webhookrelay/webhook-demo:0.16.0
|
|
func (a *Approval) Delta() string {
|
|
return fmt.Sprintf("%s -> %s", a.CurrentVersion, a.NewVersion)
|
|
}
|
|
|
|
// JSONB is stored as a JSON blob
|
|
type JSONB map[string]interface{}
|
|
|
|
func (b JSONB) Value() (driver.Value, error) {
|
|
j, err := json.Marshal(b)
|
|
return j, err
|
|
}
|
|
|
|
func (b *JSONB) Scan(src interface{}) error {
|
|
source, ok := src.([]byte)
|
|
if !ok {
|
|
return errors.New("type assertion .([]byte) failed.")
|
|
}
|
|
|
|
var i interface{}
|
|
if err := json.Unmarshal(source, &i); err != nil {
|
|
return err
|
|
}
|
|
|
|
if i == nil {
|
|
return nil
|
|
}
|
|
|
|
*b, ok = i.(map[string]interface{})
|
|
if !ok {
|
|
return errors.New("type assertion .(map[string]interface{}) failed.")
|
|
}
|
|
|
|
return nil
|
|
}
|