Skip to content

Commit

Permalink
resource: misc finalizer apis (#19474)
Browse files Browse the repository at this point in the history
  • Loading branch information
analogue authored Nov 2, 2023
1 parent a72f868 commit aaac20f
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ require (
github.com/aws/aws-sdk-go v1.44.289
github.com/coredns/coredns v1.10.1
github.com/coreos/go-oidc v2.1.0+incompatible
github.com/deckarep/golang-set/v2 v2.3.1
github.com/docker/go-connections v0.4.0
github.com/envoyproxy/go-control-plane v0.11.1
github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set/v2 v2.3.1 h1:vjmkvJt/IV27WXPyYQpAh4bRyWJc5Y435D17XQ9QU5A=
github.com/deckarep/golang-set/v2 v2.3.1/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661 h1:lrWnAyy/F72MbxIxFUzKmcMCdt9Oi8RzpAxzTNQHD7o=
github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
Expand Down
64 changes: 64 additions & 0 deletions internal/resource/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,23 @@ import (
"fmt"
"strings"

mapset "github.com/deckarep/golang-set/v2"

"github.com/hashicorp/consul/agent/dns"
"github.com/hashicorp/consul/proto-public/pbresource"
)

// MaxNameLength is the maximum length of a resource name.
const MaxNameLength = 63

// DeletionTimestampKey is the key in a resource's metadata that stores the timestamp
// when a resource was marked for deletion. This only applies to resources with finalizers.
const DeletionTimestampKey = "deletionTimestamp"

// FinalizerKey is the key in resource's metadata that stores the whitespace separated
// list of finalizers.
const FinalizerKey = "finalizers"

// ValidateName returns an error a name is not a valid resource name.
// The error will contain reference to what constitutes a valid resource name.
func ValidateName(name string) error {
Expand All @@ -20,3 +32,55 @@ func ValidateName(name string) error {
}
return nil
}

// IsMarkedForDeletion returns true if a resource has been marked for deletion,
// false otherwise.
func IsMarkedForDeletion(res *pbresource.Resource) bool {
if res.Metadata == nil {
return false
}
_, ok := res.Metadata[DeletionTimestampKey]
return ok
}

// HasFinalizers returns true if a resource has one or more finalizers, false otherwise.
func HasFinalizers(res *pbresource.Resource) bool {
return GetFinalizers(res).Cardinality() >= 1
}

// HasFinalizer returns true if a resource has a given finalizers, false otherwise.
func HasFinalizer(res *pbresource.Resource, finalizer string) bool {
return GetFinalizers(res).Contains(finalizer)
}

// AddFinalizer adds a finalizer to the given resource.
func AddFinalizer(res *pbresource.Resource, finalizer string) {
finalizerSet := GetFinalizers(res)
finalizerSet.Add(finalizer)
if res.Metadata == nil {
res.Metadata = map[string]string{}
}
res.Metadata[FinalizerKey] = strings.Join(finalizerSet.ToSlice(), " ")
}

// RemoveFinalizer removes a finalizer from the given resource.
func RemoveFinalizer(res *pbresource.Resource, finalizer string) {
finalizerSet := GetFinalizers(res)
finalizerSet.Remove(finalizer)
if res.Metadata == nil {
res.Metadata = map[string]string{}
}
res.Metadata[FinalizerKey] = strings.Join(finalizerSet.ToSlice(), " ")
}

// GetFinalizers returns the set of finalizers for the given resource.
func GetFinalizers(res *pbresource.Resource) mapset.Set[string] {
if res.Metadata == nil {
return mapset.NewSet[string]()
}
finalizers, ok := res.Metadata[FinalizerKey]
if !ok {
return mapset.NewSet[string]()
}
return mapset.NewSet[string](strings.Fields(finalizers)...)
}
53 changes: 53 additions & 0 deletions internal/resource/resource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1

package resource_test

import (
"testing"

mapset "github.com/deckarep/golang-set/v2"
"github.com/stretchr/testify/require"

"github.com/hashicorp/consul/internal/resource"
rtest "github.com/hashicorp/consul/internal/resource/resourcetest"
pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1"
)

func TestFinalizer(t *testing.T) {
t.Run("no finalizers", func(t *testing.T) {
res := rtest.Resource(pbtenancy.NamespaceType, "ns1").Build()
require.False(t, resource.HasFinalizers(res))
require.False(t, resource.HasFinalizer(res, "finalizer1"))
require.Equal(t, mapset.NewSet[string](), resource.GetFinalizers(res))
resource.RemoveFinalizer(res, "finalizer")
})

t.Run("add finalizer", func(t *testing.T) {
res := rtest.Resource(pbtenancy.NamespaceType, "ns1").Build()
resource.AddFinalizer(res, "finalizer1")
require.True(t, resource.HasFinalizers(res))
require.True(t, resource.HasFinalizer(res, "finalizer1"))
require.False(t, resource.HasFinalizer(res, "finalizer2"))
require.Equal(t, mapset.NewSet[string]("finalizer1"), resource.GetFinalizers(res))

// add duplicate -> noop
resource.AddFinalizer(res, "finalizer1")
require.Equal(t, mapset.NewSet[string]("finalizer1"), resource.GetFinalizers(res))
})

t.Run("remove finalizer", func(t *testing.T) {
res := rtest.Resource(pbtenancy.NamespaceType, "ns1").Build()
resource.AddFinalizer(res, "finalizer1")
resource.AddFinalizer(res, "finalizer2")
resource.RemoveFinalizer(res, "finalizer1")
require.False(t, resource.HasFinalizer(res, "finalizer1"))
require.True(t, resource.HasFinalizer(res, "finalizer2"))
require.Equal(t, mapset.NewSet[string]("finalizer2"), resource.GetFinalizers(res))

// remove non-existent -> noop
resource.RemoveFinalizer(res, "finalizer3")
require.Equal(t, mapset.NewSet[string]("finalizer2"), resource.GetFinalizers(res))
})

}
1 change: 1 addition & 0 deletions test-integ/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ require (
github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf // indirect
github.com/cpuguy83/dockercfg v0.3.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/deckarep/golang-set/v2 v2.3.1 // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/docker v24.0.5+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions test-integ/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set/v2 v2.3.1 h1:vjmkvJt/IV27WXPyYQpAh4bRyWJc5Y435D17XQ9QU5A=
github.com/deckarep/golang-set/v2 v2.3.1/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY=
Expand Down
1 change: 1 addition & 0 deletions test/integration/consul-container/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ require (
github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf // indirect
github.com/cpuguy83/dockercfg v0.3.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/deckarep/golang-set/v2 v2.3.1 // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/emicklei/go-restful/v3 v3.10.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions test/integration/consul-container/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set/v2 v2.3.1 h1:vjmkvJt/IV27WXPyYQpAh4bRyWJc5Y435D17XQ9QU5A=
github.com/deckarep/golang-set/v2 v2.3.1/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY=
Expand Down

0 comments on commit aaac20f

Please sign in to comment.