reading approvals from annotations

feature/approvals_count_to_ann
Karolis Rusenas 2019-04-26 10:41:01 +01:00
parent 8bff7f0c0f
commit b913dcdde4
2 changed files with 120 additions and 16 deletions

View File

@ -40,16 +40,37 @@ func (p *Provider) updateComplete(plan *UpdatePlan) error {
return p.approvalManager.Delete(getApprovalIdentifier(plan.Resource.Identifier, plan.NewVersion))
}
func (p *Provider) isApproved(event *types.Event, plan *UpdatePlan) (bool, error) {
labels := plan.Resource.GetLabels()
func getInt(key string, labels map[string]string, annotations map[string]string) (int, error) {
minApprovalsStr, ok := labels[types.KeelMinimumApprovalsLabel]
if !ok {
// no approvals required - passing
return true, nil
var (
valStr string
ok bool
)
valStr, ok = labels[key]
if ok {
valInt, err := strconv.Atoi(valStr)
if err != nil {
return 0, err
}
return valInt, nil
}
minApprovals, err := strconv.Atoi(minApprovalsStr)
valStr, ok = annotations[key]
if ok {
valInt, err := strconv.Atoi(valStr)
if err != nil {
return 0, err
}
return valInt, nil
}
return 0, nil
}
func (p *Provider) isApproved(event *types.Event, plan *UpdatePlan) (bool, error) {
minApprovals, err := getInt(types.KeelMinimumApprovalsLabel, plan.Resource.GetLabels(), plan.Resource.GetAnnotations())
if err != nil {
return false, err
}
@ -58,15 +79,16 @@ func (p *Provider) isApproved(event *types.Event, plan *UpdatePlan) (bool, error
return true, nil
}
deadline := types.KeelApprovalDeadlineDefault
// deadline
deadlineStr, ok := labels[types.KeelApprovalDeadlineLabel]
if ok {
d, err := strconv.Atoi(deadlineStr)
if err == nil {
deadline = d
}
deadline := types.KeelApprovalDeadlineDefault
d, err := getInt(types.KeelApprovalDeadlineLabel, plan.Resource.GetLabels(), plan.Resource.GetAnnotations())
if err != nil {
log.WithFields(log.Fields{
"error": err,
"resource": plan.Resource.GetName(),
}).Warn("failed to parse approvals deadline, using default value")
} else if d != 0 {
deadline = d
}
identifier := getApprovalIdentifier(plan.Resource.Identifier, plan.NewVersion)

View File

@ -8,7 +8,7 @@ import (
"github.com/keel-hq/keel/types"
apps_v1 "k8s.io/api/apps/v1"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -83,6 +83,88 @@ func TestCheckRequestedApproval(t *testing.T) {
}
}
func TestCheckRequestedApprovalAnnotation(t *testing.T) {
fp := &fakeImplementer{}
fp.namespaces = &v1.NamespaceList{
Items: []v1.Namespace{
v1.Namespace{
meta_v1.TypeMeta{},
meta_v1.ObjectMeta{Name: "xxxx"},
v1.NamespaceSpec{},
v1.NamespaceStatus{},
},
},
}
deployments := []*apps_v1.Deployment{
{
meta_v1.TypeMeta{},
meta_v1.ObjectMeta{
Name: "dep-1",
Namespace: "xxxx",
Labels: map[string]string{},
Annotations: map[string]string{
types.KeelPolicyLabel: "all",
types.KeelMinimumApprovalsLabel: "3",
types.KeelApprovalDeadlineLabel: "20",
},
},
apps_v1.DeploymentSpec{
Template: v1.PodTemplateSpec{
Spec: v1.PodSpec{
Containers: []v1.Container{
v1.Container{
Image: "gcr.io/v2-namespace/hello-world:1.1.1",
},
},
},
},
},
apps_v1.DeploymentStatus{},
},
}
grs := MustParseGRS(deployments)
grc := &k8s.GenericResourceCache{}
grc.Add(grs...)
approver := approver()
provider, err := NewProvider(fp, &fakeSender{}, approver, grc)
if err != nil {
t.Fatalf("failed to get provider: %s", err)
}
// creating "new version" event
repo := types.Repository{
Name: "gcr.io/v2-namespace/hello-world",
Tag: "1.1.2",
}
deps, err := provider.processEvent(&types.Event{Repository: repo})
if err != nil {
t.Errorf("failed to get deployments: %s", err)
}
if len(deps) != 0 {
t.Errorf("expected to find 0 updated deployment but found %d", len(deps))
}
// checking approvals
approval, err := provider.approvalManager.Get("deployment/xxxx/dep-1:1.1.2")
if err != nil {
t.Fatalf("failed to find approval, err: %s", err)
}
if approval.Provider != types.ProviderTypeKubernetes {
t.Errorf("wrong provider: %s", approval.Provider)
}
if approval.VotesRequired != 3 {
t.Errorf("expected 3 required votes, got: %d", approval.VotesRequired)
}
if approval.Deadline.Before(time.Now().Add(19 * time.Hour)) {
t.Errorf("unexpected deadline: %s", approval.Deadline)
}
}
func TestApprovedCheck(t *testing.T) {
fp := &fakeImplementer{}
fp.namespaces = &v1.NamespaceList{