resource: misc finalizer apis (#19474)

This commit is contained in:
Semir Patel 2023-11-02 15:56:02 -05:00 committed by GitHub
parent a72f868218
commit aaac20f4a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 126 additions and 0 deletions

1
go.mod
View File

@ -24,6 +24,7 @@ require (
github.com/aws/aws-sdk-go v1.44.289 github.com/aws/aws-sdk-go v1.44.289
github.com/coredns/coredns v1.10.1 github.com/coredns/coredns v1.10.1
github.com/coreos/go-oidc v2.1.0+incompatible 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/docker/go-connections v0.4.0
github.com/envoyproxy/go-control-plane v0.11.1 github.com/envoyproxy/go-control-plane v0.11.1
github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e

2
go.sum
View File

@ -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.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 h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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 h1:lrWnAyy/F72MbxIxFUzKmcMCdt9Oi8RzpAxzTNQHD7o=
github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= 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= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=

View File

@ -7,11 +7,23 @@ import (
"fmt" "fmt"
"strings" "strings"
mapset "github.com/deckarep/golang-set/v2"
"github.com/hashicorp/consul/agent/dns" "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 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. // ValidateName returns an error a name is not a valid resource name.
// The error will contain reference to what constitutes a valid resource name. // The error will contain reference to what constitutes a valid resource name.
func ValidateName(name string) error { func ValidateName(name string) error {
@ -20,3 +32,55 @@ func ValidateName(name string) error {
} }
return nil 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)...)
}

View File

@ -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))
})
}

View File

@ -53,6 +53,7 @@ require (
github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf // indirect github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf // indirect
github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // 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/distribution v2.8.2+incompatible // indirect
github.com/docker/docker v24.0.5+incompatible // indirect github.com/docker/docker v24.0.5+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-connections v0.4.0 // indirect

View File

@ -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.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 h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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 h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= 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= github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY=

View File

@ -68,6 +68,7 @@ require (
github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf // indirect github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf // indirect
github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // 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/distribution v2.8.2+incompatible // indirect
github.com/docker/go-units v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect
github.com/emicklei/go-restful/v3 v3.10.1 // indirect github.com/emicklei/go-restful/v3 v3.10.1 // indirect

View File

@ -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.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 h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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 h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= 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= github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY=