keel/provider/helm3/approvals.go

93 lines
2.5 KiB
Go
Executable File

package helm3
import (
"fmt"
"time"
"github.com/keel-hq/keel/pkg/store"
"github.com/keel-hq/keel/types"
log "github.com/sirupsen/logrus"
)
// namespace/release name:version
func getIdentifier(plan *UpdatePlan) string {
return fmt.Sprintf("%s/%s:%s", plan.Namespace, plan.Name, plan.NewVersion)
}
func (p *Provider) checkForApprovals(event *types.Event, plans []*UpdatePlan) (approvedPlans []*UpdatePlan) {
approvedPlans = []*UpdatePlan{}
for _, plan := range plans {
approved, err := p.isApproved(event, plan)
if err != nil {
log.WithFields(log.Fields{
"error": err,
"release_name": plan.Name,
"namespace": plan.Namespace,
"version": plan.NewVersion,
}).Error("provider.helm3: failed to check approval status for deployment")
continue
}
if approved {
approvedPlans = append(approvedPlans, plan)
}
}
return approvedPlans
}
// updateComplete is called after we successfully update resource
func (p *Provider) updateComplete(plan *UpdatePlan) error {
return p.approvalManager.Archive(getIdentifier(plan))
}
func (p *Provider) isApproved(event *types.Event, plan *UpdatePlan) (bool, error) {
if plan.Config.Approvals == 0 {
return true, nil
}
identifier := getIdentifier(plan)
// checking for existing approval
existing, err := p.approvalManager.Get(identifier)
if err != nil {
if err == store.ErrRecordNotFound {
// if approval doesn't exist and trigger wasn't existing approval fulfillment -
// create a new one, otherwise if several deployments rely on the same image, it would just be
// requesting approvals in a loop
if event.TriggerName == types.TriggerTypeApproval.String() {
return false, nil
}
if plan.Config.ApprovalDeadline == 0 {
plan.Config.ApprovalDeadline = types.KeelApprovalDeadlineDefault
}
// creating new one
approval := &types.Approval{
Provider: types.ProviderTypeHelm,
Identifier: identifier,
Event: event,
CurrentVersion: plan.CurrentVersion,
NewVersion: plan.NewVersion,
VotesRequired: plan.Config.Approvals,
VotesReceived: 0,
Rejected: false,
Deadline: time.Now().Add(time.Duration(plan.Config.ApprovalDeadline) * time.Hour),
}
approval.Message = fmt.Sprintf("New image is available for release %s/%s (%s).",
plan.Namespace,
plan.Name,
approval.Delta(),
)
return false, p.approvalManager.Create(approval)
}
return false, err
}
return existing.Status() == types.ApprovalStatusApproved, nil
}