Compare commits

..

7 Commits

Author SHA1 Message Date
Caleb Bron
d80ffb5c22 Merge pull request #88 from KevinJoiner/wrangler-v2
Bumps rancher/wrangler to it's tagged v2 version.
2024-01-24 08:13:33 -07:00
Kevin Joiner
e6451ba1e8 Bumps rancher/wrangler to it's tagged v2 version. 2024-01-11 16:22:55 -05:00
vardhaman22
0a2d8dff62 retry saving missed secret after intial sync 2023-09-28 09:53:35 -07:00
Kinara Shah
0132d96ec2 Merge pull request #80 from vardhaman22/k8s-1.27.4
updated deps for k8s 1.27
2023-08-30 22:23:50 -07:00
vardhaman22
06acb83e5d fix listener call 2023-08-31 10:50:15 +05:30
vardhaman22
10456ff2e6 updated deps for k8s 1.27 2023-08-23 11:45:25 +05:30
Brad Davidson
1c60bf414f Fix deadlock caused by apiserver outage during init
We had similar code to prevent blocking when calling Update(), but not in the init function.

Ref: https://github.com/rancher/rancher/issues/42278
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
2023-08-15 12:44:26 -07:00
5 changed files with 51 additions and 22 deletions

2
go.mod
View File

@@ -3,7 +3,7 @@ module github.com/rancher/dynamiclistener
go 1.20
require (
github.com/rancher/wrangler v1.1.1-0.20230831050635-df1bd5aae9df
github.com/rancher/wrangler/v2 v2.0.2
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.8.4
golang.org/x/crypto v0.11.0

4
go.sum
View File

@@ -232,8 +232,8 @@ github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/rancher/lasso v0.0.0-20230830164424-d684fdeb6f29 h1:+kige/h8/LnzWgPjB5NUIHz/pWiW/lFpqcTUkN5uulY=
github.com/rancher/lasso v0.0.0-20230830164424-d684fdeb6f29/go.mod h1:kgk9kJVMj9FIrrXU0iyM6u/9Je4bEjPImqswkTVaKsQ=
github.com/rancher/wrangler v1.1.1-0.20230831050635-df1bd5aae9df h1:WJ+aaUICHPX8HeLmHE9JL/RFHhilMfcJlqmhgpc7gJU=
github.com/rancher/wrangler v1.1.1-0.20230831050635-df1bd5aae9df/go.mod h1:4T80p+rLh2OLbjCjdExIjRHKNBgK9NUAd7eIU/gRPKk=
github.com/rancher/wrangler/v2 v2.0.2 h1:EWaWaD5Gnh8gGcLzglf/zktyuaiTi6e95c0T2RivVi8=
github.com/rancher/wrangler/v2 v2.0.2/go.mod h1:p0YJmpbUbEQ1CE1GIbhwa9gCXeBJOBsQ6F6+Nf3LeLo=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=

View File

@@ -15,7 +15,7 @@ import (
"github.com/rancher/dynamiclistener/storage/file"
"github.com/rancher/dynamiclistener/storage/kubernetes"
"github.com/rancher/dynamiclistener/storage/memory"
v1 "github.com/rancher/wrangler/pkg/generated/controllers/core/v1"
v1 "github.com/rancher/wrangler/v2/pkg/generated/controllers/core/v1"
"github.com/sirupsen/logrus"
"golang.org/x/crypto/acme/autocert"
)

View File

@@ -5,7 +5,7 @@ import (
"crypto/x509"
"github.com/rancher/dynamiclistener/factory"
v1controller "github.com/rancher/wrangler/pkg/generated/controllers/core/v1"
v1controller "github.com/rancher/wrangler/v2/pkg/generated/controllers/core/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

View File

@@ -7,13 +7,14 @@ import (
"github.com/rancher/dynamiclistener"
"github.com/rancher/dynamiclistener/cert"
"github.com/rancher/wrangler/pkg/generated/controllers/core"
v1controller "github.com/rancher/wrangler/pkg/generated/controllers/core/v1"
"github.com/rancher/wrangler/pkg/start"
"github.com/rancher/wrangler/v2/pkg/generated/controllers/core"
v1controller "github.com/rancher/wrangler/v2/pkg/generated/controllers/core/v1"
"github.com/rancher/wrangler/v2/pkg/start"
"github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/util/retry"
)
@@ -25,6 +26,7 @@ func Load(ctx context.Context, secrets v1controller.SecretController, namespace,
namespace: namespace,
storage: backing,
ctx: ctx,
initSync: &sync.Once{},
}
storage.init(secrets)
return storage
@@ -36,23 +38,18 @@ func New(ctx context.Context, core CoreGetter, namespace, name string, backing d
namespace: namespace,
storage: backing,
ctx: ctx,
initSync: &sync.Once{},
}
// lazy init
go func() {
for {
wait.PollImmediateUntilWithContext(ctx, time.Second, func(cxt context.Context) (bool, error) {
if coreFactory := core(); coreFactory != nil {
storage.init(coreFactory.Core().V1().Secret())
_ = start.All(ctx, 5, coreFactory)
return
return true, start.All(ctx, 5, coreFactory)
}
select {
case <-ctx.Done():
return
case <-time.After(time.Second):
}
}
return false, nil
})
}()
return storage
@@ -66,6 +63,8 @@ type storage struct {
secrets v1controller.SecretController
ctx context.Context
tls dynamiclistener.TLSFactory
initialized bool
initSync *sync.Once
}
func (s *storage) SetFactory(tls dynamiclistener.TLSFactory) {
@@ -92,7 +91,17 @@ func (s *storage) init(secrets v1controller.SecretController) {
})
s.secrets = secrets
secret, err := s.storage.Get()
// Asynchronously sync the backing storage to the Kubernetes secret, as doing so inline may
// block the listener from accepting new connections if the apiserver becomes unavailable
// after the Secrets controller has been initialized. We're not passing around any contexts
// here, nor does the controller accept any, so there's no good way to soft-fail with a
// reasonable timeout.
go s.syncStorage()
}
func (s *storage) syncStorage() {
var updateStorage bool
secret, err := s.Get()
if err == nil && cert.IsValidTLSSecret(secret) {
// local storage had a cached secret, ensure that it exists in Kubernetes
_, err := s.secrets.Create(&v1.Secret{
@@ -109,14 +118,20 @@ func (s *storage) init(secrets v1controller.SecretController) {
}
} else {
// local storage was empty, try to populate it
secret, err := s.secrets.Get(s.namespace, s.name, metav1.GetOptions{})
secret, err = s.secrets.Get(s.namespace, s.name, metav1.GetOptions{})
if err != nil {
if !errors.IsNotFound(err) {
logrus.Warnf("Failed to init Kubernetes secret: %v", err)
}
return
} else {
updateStorage = true
}
}
s.Lock()
defer s.Unlock()
s.initialized = true
if updateStorage {
if err := s.storage.Update(secret); err != nil {
logrus.Warnf("Failed to init backing storage secret: %v", err)
}
@@ -149,6 +164,20 @@ func (s *storage) targetSecret() (*v1.Secret, error) {
func (s *storage) saveInK8s(secret *v1.Secret) (*v1.Secret, error) {
if !s.initComplete() {
// Start a goroutine to attempt to save the secret later, once init is complete.
// If this was already handled by initComplete, it should be a no-op, or at worst get
// merged with the Kubernetes secret.
go s.initSync.Do(func() {
if err := wait.Poll(100*time.Millisecond, 15*time.Minute, func() (bool, error) {
if !s.initComplete() {
return false, nil
}
_, err := s.saveInK8s(secret)
return true, err
}); err != nil {
logrus.Errorf("Failed to save TLS secret after controller init: %v", err)
}
})
return secret, nil
}
@@ -234,5 +263,5 @@ func (s *storage) update(secret *v1.Secret) (err error) {
func (s *storage) initComplete() bool {
s.RLock()
defer s.RUnlock()
return s.secrets != nil
return s.initialized
}