Embed logging functionality to DRY code

Signed-off-by: Evans Mungai <mbuevans@gmail.com>
pull/31411/head
Evans Mungai 11 months ago
parent 9c32e34d60
commit 5ab4ca5490
No known key found for this signature in database
GPG Key ID: BBEB812143DD14E1

@ -20,6 +20,7 @@ import (
"context" "context"
"log/slog" "log/slog"
"os" "os"
"sync/atomic"
) )
// DebugEnabledFunc is a function type that determines if debug logging is enabled // DebugEnabledFunc is a function type that determines if debug logging is enabled
@ -93,3 +94,28 @@ type LoggerSetterGetter interface {
// Logger returns the logger for the object // Logger returns the logger for the object
Logger() *slog.Logger Logger() *slog.Logger
} }
type LogHolder struct {
// logger is an slog.Logger pointer to use the driver
logger atomic.Pointer[slog.Logger]
}
// Logger returns the logger for the LogHolder. If nil, returns slog.Default().
func (l *LogHolder) Logger() *slog.Logger {
if lg := l.logger.Load(); lg != nil {
return lg
}
return slog.Default() // We rarely get here, just being defensive
}
// SetLogger sets the logger for the LogHolder. If nil, sets the default logger.
func (l *LogHolder) SetLogger(newLogger *slog.Logger) {
if newLogger == nil {
l.logger.Store(slog.New(slog.DiscardHandler)) // Assume nil as discarding logs
return
}
l.logger.Store(newLogger)
}
// Ensure LogHolder implements LoggerSetterGetter
var _ LoggerSetterGetter = &LogHolder{}

@ -29,7 +29,6 @@ import (
"slices" "slices"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"text/template" "text/template"
"time" "time"
@ -41,6 +40,7 @@ import (
"sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/kio"
kyaml "sigs.k8s.io/kustomize/kyaml/yaml" kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
"helm.sh/helm/v4/internal/logging"
"helm.sh/helm/v4/pkg/chart/common" "helm.sh/helm/v4/pkg/chart/common"
chart "helm.sh/helm/v4/pkg/chart/v2" chart "helm.sh/helm/v4/pkg/chart/v2"
chartutil "helm.sh/helm/v4/pkg/chart/v2/util" chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
@ -110,11 +110,11 @@ type Configuration struct {
// HookOutputFunc called with container name and returns and expects writer that will receive the log output. // HookOutputFunc called with container name and returns and expects writer that will receive the log output.
HookOutputFunc func(namespace, pod, container string) io.Writer HookOutputFunc func(namespace, pod, container string) io.Writer
// logger is an slog.Logger pointer to use with the Configuration instance
logger atomic.Pointer[slog.Logger]
// Mutex is an exclusive lock for concurrent access to the action // Mutex is an exclusive lock for concurrent access to the action
mutex sync.Mutex mutex sync.Mutex
// Embed a LogHolder to provide logger functionality
logging.LogHolder
} }
func NewConfiguration() *Configuration { func NewConfiguration() *Configuration {
@ -554,23 +554,6 @@ func (cfg *Configuration) SetHookOutputFunc(hookOutputFunc func(_, _, _ string)
cfg.HookOutputFunc = hookOutputFunc cfg.HookOutputFunc = hookOutputFunc
} }
// Logger returns the logger for the Configuration. If nil, returns slog.Default().
func (cfg *Configuration) Logger() *slog.Logger {
if lg := cfg.logger.Load(); lg != nil {
return lg
}
return slog.Default() // We rarely get here, just be defensive
}
// SetLogger sets the logger for the Configuration. If nil, sets the default logger.
func (cfg *Configuration) SetLogger(newLogger *slog.Logger) {
if newLogger == nil {
cfg.logger.Store(slog.New(slog.DiscardHandler)) // Assume nil as discarding logs
return
}
cfg.logger.Store(newLogger)
}
func determineReleaseSSApplyMethod(serverSideApply bool) release.ApplyMethod { func determineReleaseSSApplyMethod(serverSideApply bool) release.ApplyMethod {
if serverSideApply { if serverSideApply {
return release.ApplyMethodServerSideApply return release.ApplyMethodServerSideApply

@ -30,7 +30,6 @@ import (
"reflect" "reflect"
"strings" "strings"
"sync" "sync"
"sync/atomic"
jsonpatch "github.com/evanphx/json-patch/v5" jsonpatch "github.com/evanphx/json-patch/v5"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
@ -40,6 +39,8 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client/apiutil" "sigs.k8s.io/controller-runtime/pkg/client/apiutil"
"helm.sh/helm/v4/internal/logging"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@ -82,11 +83,12 @@ type Client struct {
Factory Factory Factory Factory
// Namespace allows to bypass the kubeconfig file for the choice of the namespace // Namespace allows to bypass the kubeconfig file for the choice of the namespace
Namespace string Namespace string
// logger is an slog.Logger pointer to use with the kube client
logger atomic.Pointer[slog.Logger]
Waiter Waiter
kubeClient kubernetes.Interface kubeClient kubernetes.Interface
// Embed a LogHolder to provide logger functionality
logging.LogHolder
} }
var _ Interface = (*Client)(nil) var _ Interface = (*Client)(nil)
@ -1198,19 +1200,3 @@ func (e *joinedErrors) Error() string {
func (e *joinedErrors) Unwrap() []error { func (e *joinedErrors) Unwrap() []error {
return e.errs return e.errs
} }
// logger returns the logger for the Client. If nil, returns slog.Default().
func (c *Client) Logger() *slog.Logger {
if lg := c.logger.Load(); lg != nil {
return lg
}
return slog.Default() // We rarely get here, just being defensive
}
func (c *Client) SetLogger(newLogger *slog.Logger) {
if newLogger == nil {
c.logger.Store(slog.New(slog.DiscardHandler)) // Assume nil as discarding logs
return
}
c.logger.Store(newLogger)
}

@ -22,7 +22,6 @@ import (
"log/slog" "log/slog"
"strconv" "strconv"
"strings" "strings"
"sync/atomic"
"time" "time"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
@ -32,6 +31,7 @@ import (
"k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation"
corev1 "k8s.io/client-go/kubernetes/typed/core/v1" corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
"helm.sh/helm/v4/internal/logging"
"helm.sh/helm/v4/pkg/release" "helm.sh/helm/v4/pkg/release"
rspb "helm.sh/helm/v4/pkg/release/v1" rspb "helm.sh/helm/v4/pkg/release/v1"
) )
@ -45,8 +45,9 @@ const ConfigMapsDriverName = "ConfigMap"
// ConfigMapsInterface. // ConfigMapsInterface.
type ConfigMaps struct { type ConfigMaps struct {
impl corev1.ConfigMapInterface impl corev1.ConfigMapInterface
// logger is an slog.Logger pointer to use the driver
logger atomic.Pointer[slog.Logger] // Embed a LogHolder to provide logger functionality
logging.LogHolder
} }
// NewConfigMaps initializes a new ConfigMaps wrapping an implementation of // NewConfigMaps initializes a new ConfigMaps wrapping an implementation of
@ -281,19 +282,3 @@ func newConfigMapsObject(key string, rls *rspb.Release, lbs labels) (*v1.ConfigM
Data: map[string]string{"release": s}, Data: map[string]string{"release": s},
}, nil }, nil
} }
// logger returns the logger for the ConfigMaps driver. If nil, returns slog.Default().
func (cfgmaps *ConfigMaps) Logger() *slog.Logger {
if lg := cfgmaps.logger.Load(); lg != nil {
return lg
}
return slog.Default() // We rarely get here, just being defensive
}
func (cfgmaps *ConfigMaps) SetLogger(newLogger *slog.Logger) {
if newLogger == nil {
cfgmaps.logger.Store(slog.New(slog.DiscardHandler)) // Assume nil as discarding logs
return
}
cfgmaps.logger.Store(newLogger)
}

@ -21,8 +21,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"helm.sh/helm/v4/internal/logging"
"helm.sh/helm/v4/pkg/release" "helm.sh/helm/v4/pkg/release"
) )
@ -44,8 +44,8 @@ type Memory struct {
namespace string namespace string
// A map of namespaces to releases // A map of namespaces to releases
cache map[string]memReleases cache map[string]memReleases
// logger is an slog.Logger pointer to use the driver // Embed a LogHolder to provide logger functionality
logger atomic.Pointer[slog.Logger] logging.LogHolder
} }
// NewMemory initializes a new memory driver. // NewMemory initializes a new memory driver.
@ -253,18 +253,3 @@ func (mem *Memory) rlock() func() {
// ```defer unlock(mem.rlock())```, locks mem for reading at the // ```defer unlock(mem.rlock())```, locks mem for reading at the
// call point of defer and unlocks upon exiting the block. // call point of defer and unlocks upon exiting the block.
func unlock(fn func()) { fn() } func unlock(fn func()) { fn() }
func (mem *Memory) Logger() *slog.Logger {
if lg := mem.logger.Load(); lg != nil {
return lg
}
return slog.Default() // We rarely get here, just being defensive
}
func (mem *Memory) SetLogger(newLogger *slog.Logger) {
if newLogger == nil {
mem.logger.Store(slog.New(slog.DiscardHandler)) // Assume nil as discarding logs
return
}
mem.logger.Store(newLogger)
}

@ -22,7 +22,6 @@ import (
"log/slog" "log/slog"
"strconv" "strconv"
"strings" "strings"
"sync/atomic"
"time" "time"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
@ -32,6 +31,7 @@ import (
"k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation"
corev1 "k8s.io/client-go/kubernetes/typed/core/v1" corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
"helm.sh/helm/v4/internal/logging"
"helm.sh/helm/v4/pkg/release" "helm.sh/helm/v4/pkg/release"
rspb "helm.sh/helm/v4/pkg/release/v1" rspb "helm.sh/helm/v4/pkg/release/v1"
) )
@ -45,8 +45,8 @@ const SecretsDriverName = "Secret"
// SecretsInterface. // SecretsInterface.
type Secrets struct { type Secrets struct {
impl corev1.SecretInterface impl corev1.SecretInterface
// logger is an slog.Logger pointer to use the driver // Embed a LogHolder to provide logger functionality
logger atomic.Pointer[slog.Logger] logging.LogHolder
} }
// NewSecrets initializes a new Secrets wrapping an implementation of // NewSecrets initializes a new Secrets wrapping an implementation of
@ -278,19 +278,3 @@ func newSecretsObject(key string, rls *rspb.Release, lbs labels) (*v1.Secret, er
Data: map[string][]byte{"release": []byte(s)}, Data: map[string][]byte{"release": []byte(s)},
}, nil }, nil
} }
// logger returns the logger for the Secrets driver. If nil, returns slog.Default().
func (secrets *Secrets) Logger() *slog.Logger {
if lg := secrets.logger.Load(); lg != nil {
return lg
}
return slog.Default() // We rarely get here, just being defensive
}
func (secrets *Secrets) SetLogger(newLogger *slog.Logger) {
if newLogger == nil {
secrets.logger.Store(slog.New(slog.DiscardHandler)) // Assume nil as discarding logs
return
}
secrets.logger.Store(newLogger)
}

@ -22,7 +22,6 @@ import (
"maps" "maps"
"sort" "sort"
"strconv" "strconv"
"sync/atomic"
"time" "time"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
@ -33,6 +32,7 @@ import (
// Import pq for postgres dialect // Import pq for postgres dialect
_ "github.com/lib/pq" _ "github.com/lib/pq"
"helm.sh/helm/v4/internal/logging"
"helm.sh/helm/v4/pkg/release" "helm.sh/helm/v4/pkg/release"
rspb "helm.sh/helm/v4/pkg/release/v1" rspb "helm.sh/helm/v4/pkg/release/v1"
) )
@ -90,8 +90,8 @@ type SQL struct {
db *sqlx.DB db *sqlx.DB
namespace string namespace string
statementBuilder sq.StatementBuilderType statementBuilder sq.StatementBuilderType
// logger is an slog.Logger pointer to use the driver // Embed a LogHolder to provide logger functionality
logger atomic.Pointer[slog.Logger] logging.LogHolder
} }
// Name returns the name of the driver. // Name returns the name of the driver.
@ -706,19 +706,3 @@ func getReleaseSystemLabels(rls *rspb.Release) map[string]string {
"version": strconv.Itoa(rls.Version), "version": strconv.Itoa(rls.Version),
} }
} }
// logger returns the logger for the SQL driver. If nil, returns slog.Default().
func (s *SQL) Logger() *slog.Logger {
if lg := s.logger.Load(); lg != nil {
return lg
}
return slog.Default() // We rarely get here, just being defensive
}
func (s *SQL) SetLogger(newLogger *slog.Logger) {
if newLogger == nil {
s.logger.Store(slog.New(slog.DiscardHandler)) // Assume nil as discarding logs
return
}
s.logger.Store(newLogger)
}

@ -21,7 +21,6 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"strings" "strings"
"sync/atomic"
"helm.sh/helm/v4/internal/logging" "helm.sh/helm/v4/internal/logging"
"helm.sh/helm/v4/pkg/release" "helm.sh/helm/v4/pkg/release"
@ -47,8 +46,8 @@ type Storage struct {
// ignored (meaning no limits are imposed). // ignored (meaning no limits are imposed).
MaxHistory int MaxHistory int
// logger is an slog.Logger pointer to use the storage engine // Embed a LogHolder to provide logger functionality
logger atomic.Pointer[slog.Logger] logging.LogHolder
} }
// Get retrieves the release from storage. An error is returned // Get retrieves the release from storage. An error is returned
@ -349,19 +348,3 @@ func Init(d driver.Driver) *Storage {
} }
return s return s
} }
// logger returns the logger for the Storage. If nil, returns slog.Default().
func (s *Storage) Logger() *slog.Logger {
if lg := s.logger.Load(); lg != nil {
return lg
}
return slog.Default() // We rarely get here, just being defensive
}
func (s *Storage) SetLogger(newLogger *slog.Logger) {
if newLogger == nil {
s.logger.Store(slog.New(slog.DiscardHandler)) // Assume nil as discarding logs
return
}
s.logger.Store(newLogger)
}

Loading…
Cancel
Save